blob: cc168042baa9f3e4748e1fd37af69ea33c89a101 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
78#ifdef ANI_BUS_TYPE_SDIO
79#include <wlan_sal_misc.h>
80#endif // ANI_BUS_TYPE_SDIO
81#include <vos_api.h>
82#include <vos_sched.h>
83#include <vos_power.h>
84#include <linux/etherdevice.h>
85#include <linux/firmware.h>
86#ifdef ANI_BUS_TYPE_SDIO
87#include <linux/mmc/sdio_func.h>
88#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32))
89// added in 2.6.32, need to define locally if using an earlier kernel
90#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev)
91#endif
92#endif // ANI_BUS_TYPE_SDIO
93#ifdef ANI_BUS_TYPE_PLATFORM
94#include <linux/wcnss_wlan.h>
95#endif //ANI_BUS_TYPE_PLATFORM
96#ifdef ANI_BUS_TYPE_PCI
97#include "wcnss_wlan.h"
98#endif /* ANI_BUS_TYPE_PCI */
99#include <wlan_hdd_tx_rx.h>
100#include <palTimer.h>
101#include <wniApi.h>
102#include <wlan_nlink_srv.h>
103#include <wlan_btc_svc.h>
104#include <wlan_hdd_cfg.h>
105#include <wlan_ptt_sock_svc.h>
106#include <wlan_hdd_wowl.h>
107#include <wlan_hdd_misc.h>
108#include <wlan_hdd_wext.h>
109#ifdef WLAN_BTAMP_FEATURE
110#include <bap_hdd_main.h>
111#include <bapInternal.h>
112#endif // WLAN_BTAMP_FEATURE
113
114#ifdef CONFIG_CFG80211
115#include <linux/wireless.h>
116#include <net/cfg80211.h>
117#include "wlan_hdd_cfg80211.h"
118#include "wlan_hdd_p2p.h"
119#endif
120#include <linux/rtnetlink.h>
121#ifdef ANI_MANF_DIAG
122int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
123#endif
124#ifdef WLAN_SOFTAP_FEATURE
125#include "sapApi.h"
126#include <linux/semaphore.h>
127#include <mach/subsystem_restart.h>
128#include <wlan_hdd_hostapd.h>
129#include <wlan_hdd_softap_tx_rx.h>
130#endif
131#ifdef FEATURE_WLAN_INTEGRATED_SOC
132#include "cfgApi.h"
133#endif
134#include "wlan_hdd_dev_pwr.h"
135#ifdef WLAN_BTAMP_FEATURE
136#include "bap_hdd_misc.h"
137#endif
138#ifdef FEATURE_WLAN_INTEGRATED_SOC
139#include "wlan_qct_pal_trace.h"
140#endif /* FEATURE_WLAN_INTEGRATED_SOC */
141#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800142#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530143#ifdef FEATURE_WLAN_TDLS
144#include "wlan_hdd_tdls.h"
145#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700146
147#ifdef MODULE
148#define WLAN_MODULE_NAME module_name(THIS_MODULE)
149#else
150#define WLAN_MODULE_NAME "wlan"
151#endif
152
153#ifdef TIMER_MANAGER
154#define TIMER_MANAGER_STR " +TIMER_MANAGER"
155#else
156#define TIMER_MANAGER_STR ""
157#endif
158
159#ifdef MEMORY_DEBUG
160#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
161#else
162#define MEMORY_DEBUG_STR ""
163#endif
164
165/* the Android framework expects this param even though we don't use it */
166#define BUF_LEN 20
167static char fwpath[BUF_LEN];
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700168#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700169static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700170#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700171
Jeff Johnsone7245742012-09-05 17:12:55 -0700172/*
173 * The rate at which the driver sends RESTART event to supplicant
174 * once the function 'vos_wlanRestart()' is called
175 *
176 */
177#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
178#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
179#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -0700180static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700181#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700182/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700183static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700184
185//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700186static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
187static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
188static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
189void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
190
Jeff Johnson295189b2012-06-20 16:38:30 -0700191v_U16_t hdd_select_queue(struct net_device *dev,
192 struct sk_buff *skb);
193
194#ifdef WLAN_FEATURE_PACKET_FILTERING
195static void hdd_set_multicast_list(struct net_device *dev);
196#endif
197
198void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
199
200extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
201
202static int hdd_netdev_notifier_call(struct notifier_block * nb,
203 unsigned long state,
204 void *ndev)
205{
206 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700207 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
208 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -0700209#ifdef WLAN_BTAMP_FEATURE
210 VOS_STATUS status;
211 hdd_context_t *pHddCtx;
212#endif
213
214 //Make sure that this callback corresponds to our device.
215 if((strncmp( dev->name, "wlan", 4 )) &&
Jeff Johnsone7245742012-09-05 17:12:55 -0700216 (strncmp( dev->name, "p2p", 3))
Jeff Johnson295189b2012-06-20 16:38:30 -0700217 )
218 return NOTIFY_DONE;
219
220#ifdef CONFIG_CFG80211
221 if (!dev->ieee80211_ptr)
222 return NOTIFY_DONE;
223#endif
224
Jeff Johnson295189b2012-06-20 16:38:30 -0700225
226 if(NULL == pAdapter)
227 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800228 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700229 VOS_ASSERT(0);
230 return NOTIFY_DONE;
231 }
232
233 hddLog(VOS_TRACE_LEVEL_INFO,"%s: New Net Device State = %lu", __func__, state);
234
235 switch (state) {
236 case NETDEV_REGISTER:
237 break;
238
239 case NETDEV_UNREGISTER:
240 break;
241
242 case NETDEV_UP:
243 break;
244
245 case NETDEV_DOWN:
246 break;
247
248 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700249 if(TRUE == pAdapter->isLinkUpSvcNeeded)
250 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 break;
252
253 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700254 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700255 {
256 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800257 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700258 hdd_abort_mac_scan(pAdapter->pHddCtx);
259 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800260 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700261 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
262 if(!result)
263 {
264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800265 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700266 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700267 }
268 }
269 else
270 {
271 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700272 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700273 }
274#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700275 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700276 status = WLANBAP_StopAmp();
277 if(VOS_STATUS_SUCCESS != status )
278 {
279 pHddCtx->isAmpAllowed = VOS_TRUE;
280 hddLog(VOS_TRACE_LEVEL_FATAL,
281 "%s: Failed to stop AMP", __func__);
282 }
283 else
284 {
285 //a state m/c implementation in PAL is TBD to avoid this delay
286 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700287 if ( pHddCtx->isAmpAllowed )
288 {
289 WLANBAP_DeregisterFromHCI();
290 pHddCtx->isAmpAllowed = VOS_FALSE;
291 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700292 }
293#endif //WLAN_BTAMP_FEATURE
294 break;
295
296 default:
297 break;
298 }
299
300 return NOTIFY_DONE;
301}
302
303struct notifier_block hdd_netdev_notifier = {
304 .notifier_call = hdd_netdev_notifier_call,
305};
306
307/*---------------------------------------------------------------------------
308 * Function definitions
309 *-------------------------------------------------------------------------*/
310extern int isWDresetInProgress(void);
311#ifdef CONFIG_HAS_EARLYSUSPEND
312extern void register_wlan_suspend(void);
313extern void unregister_wlan_suspend(void);
314void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
315void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
316#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700317//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700318static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700319#ifndef MODULE
320/* current con_mode - used only for statically linked driver
321 * con_mode is changed by userspace to indicate a mode change which will
322 * result in calling the module exit and init functions. The module
323 * exit function will clean up based on the value of con_mode prior to it
324 * being changed by userspace. So curr_con_mode records the current con_mode
325 * for exit when con_mode becomes the next mode for init
326 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700327static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700328#endif
329
330#ifdef FEATURE_WLAN_INTEGRATED_SOC
331/**---------------------------------------------------------------------------
332
333 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
334
335 Called immediately after the cfg.ini is read in order to configure
336 the desired trace levels in the WDI.
337
338 \param - moduleId - module whose trace level is being configured
339 \param - bitmask - bitmask of log levels to be enabled
340
341 \return - void
342
343 --------------------------------------------------------------------------*/
344static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
345{
346 wpt_tracelevel level;
347
348 /* if the bitmask is the default value, then a bitmask was not
349 specified in cfg.ini, so leave the logging level alone (it
350 will remain at the "compiled in" default value) */
351 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
352 {
353 return;
354 }
355
356 /* a mask was specified. start by disabling all logging */
357 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
358
359 /* now cycle through the bitmask until all "set" bits are serviced */
360 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
361 while (0 != bitmask)
362 {
363 if (bitmask & 1)
364 {
365 wpalTraceSetLevel(moduleId, level, 1);
366 }
367 level++;
368 bitmask >>= 1;
369 }
370}
371#endif /* FEATURE_WLAN_INTEGRATED_SOC */
372
373int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
374{
375 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
376 hdd_priv_data_t priv_data;
377 tANI_U8 *command = NULL;
378 int ret = 0;
379
380 if (NULL == pAdapter)
381 {
382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700383 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700384 ret = -ENODEV;
385 goto exit;
386 }
387
Jeff Johnsone7245742012-09-05 17:12:55 -0700388 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700389 {
390 ret = -EINVAL;
391 goto exit;
392 }
393
394 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
395 {
396 ret = -EFAULT;
397 goto exit;
398 }
399
400 command = kmalloc(priv_data.total_len, GFP_KERNEL);
401 if (!command)
402 {
403 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700404 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700405 ret = -ENOMEM;
406 goto exit;
407 }
408
409 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
410 {
411 ret = -EFAULT;
412 goto exit;
413 }
414
415 if ((SIOCDEVPRIVATE + 1) == cmd)
416 {
417 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
418
419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700420 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700421
422 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
423 {
424 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
425 sizeof(tSirMacAddr)))
426 {
427 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700428 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700429 ret = -EFAULT;
430 }
431 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700432 else if(strncmp(priv_data.buf, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700433 {
434 tANI_U8 *ptr = (tANI_U8*)priv_data.buf ;
435 int ret = 0 ;
436
437 /* Change band request received */
438
439 /* First 8 bytes will have "SETBAND " and
440 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700441 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700442 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, priv_data.buf, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700443
444 /* Change band request received */
445 ret = hdd_setBand_helper(dev, ptr);
446 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700447 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
448 {
449 char *country_code;
450
451 country_code = command + 8;
452 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
453 pAdapter, pHddCtx->pvosContext);
454 if( 0 != ret )
455 {
456 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
457 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
458
459 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700460 }
461 /*
462 command should be a string having format
463 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
464 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -0700465 else if(strncmp(priv_data.buf, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700466 {
467 tANI_U8 *ptr = (tANI_U8*)priv_data.buf;
468
469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700470 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700471
472 ret = sapSetPreferredChannel(dev, ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700473 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700474 else {
475 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
476 __func__, command);
477 }
478
Jeff Johnson295189b2012-06-20 16:38:30 -0700479 }
480exit:
481 if (command)
482 {
483 kfree(command);
484 }
485 return ret;
486}
487
488/**---------------------------------------------------------------------------
489
490 \brief hdd_open() - HDD Open function
491
492 This is called in response to ifconfig up
493
494 \param - dev Pointer to net_device structure
495
496 \return - 0 for success non-zero for failure
497
498 --------------------------------------------------------------------------*/
499int hdd_open (struct net_device *dev)
500{
501 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
502 hdd_context_t *pHddCtx;
503 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
504 VOS_STATUS status;
505 v_BOOL_t in_standby = TRUE;
506
507 if (NULL == pAdapter)
508 {
509 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700510 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700511 return -ENODEV;
512 }
513
514 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
515 if (NULL == pHddCtx)
516 {
517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700518 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700519 return -ENODEV;
520 }
521
522 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
523 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
524 {
525 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
526 {
527 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
528 "standby", __func__, pAdapter->device_mode);
529 in_standby = FALSE;
530 break;
531 }
532 else
533 {
534 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
535 pAdapterNode = pNext;
536 }
537 }
538
539 if (TRUE == in_standby)
540 {
541 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
542 {
543 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
544 "wlan out of power save", __func__);
545 return -EINVAL;
546 }
547 }
548
549 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
550 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
551 {
552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700553 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700554 /* Enable TX queues only when we are connected */
555 netif_tx_start_all_queues(dev);
556 }
557
558 return 0;
559}
560
561int hdd_mon_open (struct net_device *dev)
562{
563 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
564
565 if(pAdapter == NULL) {
566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700567 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800568 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700569 }
570
571 netif_start_queue(dev);
572
573 return 0;
574}
575/**---------------------------------------------------------------------------
576
577 \brief hdd_stop() - HDD stop function
578
579 This is called in response to ifconfig down
580
581 \param - dev Pointer to net_device structure
582
583 \return - 0 for success non-zero for failure
584
585 --------------------------------------------------------------------------*/
586
587int hdd_stop (struct net_device *dev)
588{
589 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
590 hdd_context_t *pHddCtx;
591 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
592 VOS_STATUS status;
593 v_BOOL_t enter_standby = TRUE;
594
595 ENTER();
596
597 if (NULL == pAdapter)
598 {
599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700600 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700601 return -ENODEV;
602 }
603
604 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
605 if (NULL == pHddCtx)
606 {
607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700608 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700609 return -ENODEV;
610 }
611
612 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
613 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
614 netif_tx_disable(pAdapter->dev);
615 netif_carrier_off(pAdapter->dev);
616
617
618 /* SoftAP ifaces should never go in power save mode
619 making sure same here. */
620 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
621 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
622#ifdef WLAN_FEATURE_P2P
623 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
624#endif
625 )
626 {
627 /* SoftAP mode, so return from here */
628 EXIT();
629 return 0;
630 }
631
632 /* Find if any iface is up then
633 if any iface is up then can't put device to sleep/ power save mode. */
634 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
635 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
636 {
637 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
638 {
639 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
640 "put device to sleep", __func__, pAdapter->device_mode);
641 enter_standby = FALSE;
642 break;
643 }
644 else
645 {
646 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
647 pAdapterNode = pNext;
648 }
649 }
650
651 if (TRUE == enter_standby)
652 {
653 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
654 "entering standby", __func__);
655 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
656 {
657 /*log and return success*/
658 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
659 "wlan in power save", __func__);
660 }
661 }
662
663 EXIT();
664 return 0;
665}
666
667/**---------------------------------------------------------------------------
668
669 \brief hdd_uninit() - HDD uninit function
670
671 This is called during the netdev unregister to uninitialize all data
672associated with the device
673
674 \param - dev Pointer to net_device structure
675
676 \return - void
677
678 --------------------------------------------------------------------------*/
679static void hdd_uninit (struct net_device *dev)
680{
681 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
682
683 ENTER();
684
685 do
686 {
687 if (NULL == pAdapter)
688 {
689 hddLog(VOS_TRACE_LEVEL_FATAL,
690 "%s: NULL pAdapter", __func__);
691 break;
692 }
693
694 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
695 {
696 hddLog(VOS_TRACE_LEVEL_FATAL,
697 "%s: Invalid magic", __func__);
698 break;
699 }
700
701 if (NULL == pAdapter->pHddCtx)
702 {
703 hddLog(VOS_TRACE_LEVEL_FATAL,
704 "%s: NULL pHddCtx", __func__);
705 break;
706 }
707
708 if (dev != pAdapter->dev)
709 {
710 hddLog(VOS_TRACE_LEVEL_FATAL,
711 "%s: Invalid device reference", __func__);
712 /* we haven't validated all cases so let this go for now */
713 }
714
715 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
716
717 /* after uninit our adapter structure will no longer be valid */
718 pAdapter->dev = NULL;
719 pAdapter->magic = 0;
720 } while (0);
721
722 EXIT();
723}
724
725/**---------------------------------------------------------------------------
726
727 \brief hdd_release_firmware() -
728
729 This function calls the release firmware API to free the firmware buffer.
730
731 \param - pFileName Pointer to the File Name.
732 pCtx - Pointer to the adapter .
733
734
735 \return - 0 for success, non zero for failure
736
737 --------------------------------------------------------------------------*/
738
739VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
740{
741 VOS_STATUS status = VOS_STATUS_SUCCESS;
742 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
743 ENTER();
744
745
746 if (!strcmp(WLAN_FW_FILE, pFileName)) {
747
748 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
749
750 if(pHddCtx->fw) {
751 release_firmware(pHddCtx->fw);
752 pHddCtx->fw = NULL;
753 }
754 else
755 status = VOS_STATUS_E_FAILURE;
756 }
757 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
758 if(pHddCtx->nv) {
759 release_firmware(pHddCtx->nv);
760 pHddCtx->nv = NULL;
761 }
762 else
763 status = VOS_STATUS_E_FAILURE;
764
765 }
766
767 EXIT();
768 return status;
769}
770
771/**---------------------------------------------------------------------------
772
773 \brief hdd_request_firmware() -
774
775 This function reads the firmware file using the request firmware
776 API and returns the the firmware data and the firmware file size.
777
778 \param - pfileName - Pointer to the file name.
779 - pCtx - Pointer to the adapter .
780 - ppfw_data - Pointer to the pointer of the firmware data.
781 - pSize - Pointer to the file size.
782
783 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
784
785 --------------------------------------------------------------------------*/
786
787
788VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
789{
790 int status;
791 VOS_STATUS retval = VOS_STATUS_SUCCESS;
792 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
793 ENTER();
794
795 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
796
797 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
798
799 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
800 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
801 __func__, pfileName);
802 retval = VOS_STATUS_E_FAILURE;
803 }
804
805 else {
806 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
807 *pSize = pHddCtx->fw->size;
808 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
809 __func__, *pSize);
810 }
811 }
812 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
813
814 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
815
816 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
817 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
818 __func__, pfileName);
819 retval = VOS_STATUS_E_FAILURE;
820 }
821
822 else {
823 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
824 *pSize = pHddCtx->nv->size;
825 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
826 __func__, *pSize);
827 }
828 }
829
830 EXIT();
831 return retval;
832}
833/**---------------------------------------------------------------------------
834 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
835
836 This is the function invoked by SME to inform the result of a full power
837 request issued by HDD
838
839 \param - callbackcontext - Pointer to cookie
840 status - result of request
841
842 \return - None
843
844--------------------------------------------------------------------------*/
845void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
846{
847 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
848
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700849 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -0700850 if(&pHddCtx->full_pwr_comp_var)
851 {
852 complete(&pHddCtx->full_pwr_comp_var);
853 }
854}
855
856/**---------------------------------------------------------------------------
857
858 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
859
860 This is the function invoked by SME to inform the result of BMPS
861 request issued by HDD
862
863 \param - callbackcontext - Pointer to cookie
864 status - result of request
865
866 \return - None
867
868--------------------------------------------------------------------------*/
869void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
870{
871
872 struct completion *completion_var = (struct completion*) callbackContext;
873
874 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
875 if(completion_var != NULL)
876 {
877 complete(completion_var);
878 }
879}
880
881/**---------------------------------------------------------------------------
882
883 \brief hdd_get_cfg_file_size() -
884
885 This function reads the configuration file using the request firmware
886 API and returns the configuration file size.
887
888 \param - pCtx - Pointer to the adapter .
889 - pFileName - Pointer to the file name.
890 - pBufSize - Pointer to the buffer size.
891
892 \return - 0 for success, non zero for failure
893
894 --------------------------------------------------------------------------*/
895
896VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
897{
898 int status;
899 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
900
901 ENTER();
902
903 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
904
905 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
906 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
907 status = VOS_STATUS_E_FAILURE;
908 }
909 else {
910 *pBufSize = pHddCtx->fw->size;
911 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
912 release_firmware(pHddCtx->fw);
913 pHddCtx->fw = NULL;
914 }
915
916 EXIT();
917 return VOS_STATUS_SUCCESS;
918}
919
920/**---------------------------------------------------------------------------
921
922 \brief hdd_read_cfg_file() -
923
924 This function reads the configuration file using the request firmware
925 API and returns the cfg data and the buffer size of the configuration file.
926
927 \param - pCtx - Pointer to the adapter .
928 - pFileName - Pointer to the file name.
929 - pBuffer - Pointer to the data buffer.
930 - pBufSize - Pointer to the buffer size.
931
932 \return - 0 for success, non zero for failure
933
934 --------------------------------------------------------------------------*/
935
936VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
937 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
938{
939 int status;
940 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
941
942 ENTER();
943
944 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
945
946 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
947 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
948 return VOS_STATUS_E_FAILURE;
949 }
950 else {
951 if(*pBufSize != pHddCtx->fw->size) {
952 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
953 "file size", __func__);
954 release_firmware(pHddCtx->fw);
955 pHddCtx->fw = NULL;
956 return VOS_STATUS_E_FAILURE;
957 }
958 else {
959 if(pBuffer) {
960 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
961 }
962 release_firmware(pHddCtx->fw);
963 pHddCtx->fw = NULL;
964 }
965 }
966
967 EXIT();
968
969 return VOS_STATUS_SUCCESS;
970}
971
972/**---------------------------------------------------------------------------
973
974 \brief hdd_set_mac_addr_cb() -
975
976 This function is the call back function for setting the station
977 mac adrress called by ccm module to indicate the
978 success/failure result.
979
980 \param - hHal - Pointer to the hal module.
981 - result - returns the result of the set mac address.
982
983 \return - void
984
985 --------------------------------------------------------------------------*/
986#ifndef FEATURE_WLAN_INTEGRATED_SOC
987static void hdd_set_mac_addr_cb( tHalHandle hHal, tANI_S32 result )
988{
989 // ignore the STA_ID response for now.
990
991 VOS_ASSERT( CCM_IS_RESULT_SUCCESS( result ) );
992}
993#endif
994
995
996/**---------------------------------------------------------------------------
997
998 \brief hdd_set_mac_address() -
999
1000 This function sets the user specified mac address using
1001 the command ifconfig wlanX hw ether <mac adress>.
1002
1003 \param - dev - Pointer to the net device.
1004 - addr - Pointer to the sockaddr.
1005 \return - 0 for success, non zero for failure
1006
1007 --------------------------------------------------------------------------*/
1008
1009static int hdd_set_mac_address(struct net_device *dev, void *addr)
1010{
1011 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1012 struct sockaddr *psta_mac_addr = addr;
1013 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1014
1015 ENTER();
1016
1017 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1018
1019#ifdef HDD_SESSIONIZE
1020 // set the MAC address though the STA ID CFG.
1021 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
1022 (v_U8_t *)&pAdapter->macAddressCurrent,
1023 sizeof( pAdapter->macAddressCurrent ),
1024 hdd_set_mac_addr_cb, VOS_FALSE );
1025#endif
1026
1027 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1028
1029 EXIT();
1030 return halStatus;
1031}
1032
1033tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
1034{
1035 int i;
1036 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1037 {
1038 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
1039 break;
1040 }
1041
1042 if( VOS_MAX_CONCURRENCY_PERSONA == i)
1043 return NULL;
1044
1045 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
1046 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
1047}
1048
1049void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
1050{
1051 int i;
1052 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1053 {
1054 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
1055 {
1056 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
1057 break;
1058 }
1059 }
1060 return;
1061}
1062
1063#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1064 static struct net_device_ops wlan_drv_ops = {
1065 .ndo_open = hdd_open,
1066 .ndo_stop = hdd_stop,
1067 .ndo_uninit = hdd_uninit,
1068 .ndo_start_xmit = hdd_hard_start_xmit,
1069 .ndo_tx_timeout = hdd_tx_timeout,
1070 .ndo_get_stats = hdd_stats,
1071 .ndo_do_ioctl = hdd_ioctl,
1072 .ndo_set_mac_address = hdd_set_mac_address,
1073 .ndo_select_queue = hdd_select_queue,
1074#ifdef WLAN_FEATURE_PACKET_FILTERING
1075#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
1076 .ndo_set_rx_mode = hdd_set_multicast_list,
1077#else
1078 .ndo_set_multicast_list = hdd_set_multicast_list,
1079#endif //LINUX_VERSION_CODE
1080#endif
1081 };
1082#ifdef CONFIG_CFG80211
1083 static struct net_device_ops wlan_mon_drv_ops = {
1084 .ndo_open = hdd_mon_open,
1085 .ndo_stop = hdd_stop,
1086 .ndo_uninit = hdd_uninit,
1087 .ndo_start_xmit = hdd_mon_hard_start_xmit,
1088 .ndo_tx_timeout = hdd_tx_timeout,
1089 .ndo_get_stats = hdd_stats,
1090 .ndo_do_ioctl = hdd_ioctl,
1091 .ndo_set_mac_address = hdd_set_mac_address,
1092 };
1093#endif
1094
1095#endif
1096
1097void hdd_set_station_ops( struct net_device *pWlanDev )
1098{
1099#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1100 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
1101 pWlanDev->netdev_ops = &wlan_drv_ops;
1102#else
1103 pWlanDev->open = hdd_open;
1104 pWlanDev->stop = hdd_stop;
1105 pWlanDev->uninit = hdd_uninit;
1106 pWlanDev->hard_start_xmit = NULL;
1107 pWlanDev->tx_timeout = hdd_tx_timeout;
1108 pWlanDev->get_stats = hdd_stats;
1109 pWlanDev->do_ioctl = hdd_ioctl;
1110 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
1111 pWlanDev->set_mac_address = hdd_set_mac_address;
1112#endif
1113}
1114
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001115static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07001116{
1117 struct net_device *pWlanDev = NULL;
1118 hdd_adapter_t *pAdapter = NULL;
1119#ifdef CONFIG_CFG80211
1120 /*
1121 * cfg80211 initialization and registration....
1122 */
1123 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
1124
1125#else
1126 //Allocate the net_device and private data (station ctx)
1127 pWlanDev = alloc_etherdev_mq(sizeof( hdd_adapter_t ), NUM_TX_QUEUES);
1128
1129#endif
1130
1131 if(pWlanDev != NULL)
1132 {
1133
1134 //Save the pointer to the net_device in the HDD adapter
1135 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
1136
1137#ifndef CONFIG_CFG80211
1138 //Init the net_device structure
1139 ether_setup(pWlanDev);
1140#endif
1141
1142 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
1143
1144 pAdapter->dev = pWlanDev;
1145 pAdapter->pHddCtx = pHddCtx;
1146 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1147
1148 init_completion(&pAdapter->session_open_comp_var);
1149 init_completion(&pAdapter->session_close_comp_var);
1150 init_completion(&pAdapter->disconnect_comp_var);
1151 init_completion(&pAdapter->linkup_event_var);
1152 init_completion(&pAdapter->cancel_rem_on_chan_var);
1153 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001154#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1155 init_completion(&pAdapter->offchannel_tx_event);
1156#endif
1157#ifdef CONFIG_CFG80211
1158 init_completion(&pAdapter->tx_action_cnf_event);
1159#endif
1160 init_completion(&pHddCtx->mc_sus_event_var);
1161 init_completion(&pHddCtx->tx_sus_event_var);
1162
Jeff Johnson295189b2012-06-20 16:38:30 -07001163 pAdapter->isLinkUpSvcNeeded = FALSE;
1164 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1165 //Init the net_device structure
1166 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1167
1168 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1169 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1170 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1171 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1172
1173 hdd_set_station_ops( pAdapter->dev );
1174
1175 pWlanDev->destructor = free_netdev;
1176#ifdef CONFIG_CFG80211
1177 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1178 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1179 pAdapter->wdev.netdev = pWlanDev;
1180#endif
1181 /* set pWlanDev's parent to underlying device */
1182 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1183 }
1184
1185 return pAdapter;
1186}
1187
1188VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1189{
1190 struct net_device *pWlanDev = pAdapter->dev;
1191 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1192 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1193 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1194
1195 if( rtnl_lock_held )
1196 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001197 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001198 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1199 {
1200 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1201 return VOS_STATUS_E_FAILURE;
1202 }
1203 }
1204 if (register_netdevice(pWlanDev))
1205 {
1206 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1207 return VOS_STATUS_E_FAILURE;
1208 }
1209 }
1210 else
1211 {
1212 if(register_netdev(pWlanDev))
1213 {
1214 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1215 return VOS_STATUS_E_FAILURE;
1216 }
1217 }
1218 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1219
1220 return VOS_STATUS_SUCCESS;
1221}
1222
1223eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1224{
1225 if(pContext != NULL)
1226 {
1227 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1228
1229 /* need to make sure all of our scheduled work has completed.
1230 * This callback is called from MC thread context, so it is safe to
1231 * to call below flush workqueue API from here.
1232 */
1233 flush_scheduled_work();
1234 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1235 }
1236 return eHAL_STATUS_SUCCESS;
1237}
1238
1239VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1240{
1241 struct net_device *pWlanDev = pAdapter->dev;
1242 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1243 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1244 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1245 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1246 int rc = 0;
1247
1248 INIT_COMPLETION(pAdapter->session_open_comp_var);
1249 //Open a SME session for future operation
1250 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1251 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1252 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1253 {
1254 hddLog(VOS_TRACE_LEVEL_FATAL,
1255 "sme_OpenSession() failed with status code %08d [x%08lx]",
1256 halStatus, halStatus );
1257 status = VOS_STATUS_E_FAILURE;
1258 goto error_sme_open;
1259 }
1260
1261 //Block on a completion variable. Can't wait forever though.
1262 rc = wait_for_completion_interruptible_timeout(
1263 &pAdapter->session_open_comp_var,
1264 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1265 if (!rc)
1266 {
1267 hddLog(VOS_TRACE_LEVEL_FATAL,
1268 "Session is not opened within timeout period code %08d", rc );
1269 status = VOS_STATUS_E_FAILURE;
1270 goto error_sme_open;
1271 }
1272
1273 // Register wireless extensions
1274 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1275 {
1276 hddLog(VOS_TRACE_LEVEL_FATAL,
1277 "hdd_register_wext() failed with status code %08d [x%08lx]",
1278 halStatus, halStatus );
1279 status = VOS_STATUS_E_FAILURE;
1280 goto error_register_wext;
1281 }
1282 //Safe to register the hard_start_xmit function again
1283#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1284 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1285#else
1286 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1287#endif
1288
1289 //Set the Connection State to Not Connected
1290 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1291
1292 //Set the default operation channel
1293 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1294
1295 /* Make the default Auth Type as OPEN*/
1296 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1297
1298 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1299 {
1300 hddLog(VOS_TRACE_LEVEL_FATAL,
1301 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1302 status, status );
1303 goto error_init_txrx;
1304 }
1305
1306 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1307
1308 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1309 {
1310 hddLog(VOS_TRACE_LEVEL_FATAL,
1311 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1312 status, status );
1313 goto error_wmm_init;
1314 }
1315
1316 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1317
1318 return VOS_STATUS_SUCCESS;
1319
1320error_wmm_init:
1321 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1322 hdd_deinit_tx_rx(pAdapter);
1323error_init_txrx:
1324 hdd_UnregisterWext(pWlanDev);
1325error_register_wext:
1326 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1327 {
1328 INIT_COMPLETION(pAdapter->session_close_comp_var);
1329 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1330 pAdapter->sessionId,
1331 hdd_smeCloseSessionCallback, pAdapter ) )
1332 {
1333 //Block on a completion variable. Can't wait forever though.
1334 wait_for_completion_interruptible_timeout(
1335 &pAdapter->session_close_comp_var,
1336 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1337 }
1338}
1339error_sme_open:
1340 return status;
1341}
1342
Jeff Johnson295189b2012-06-20 16:38:30 -07001343#ifdef CONFIG_CFG80211
1344void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1345{
1346 hdd_cfg80211_state_t *cfgState;
1347
1348 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1349
1350 if( NULL != cfgState->buf )
1351 {
1352 int rc;
1353 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1354 rc = wait_for_completion_interruptible_timeout(
1355 &pAdapter->tx_action_cnf_event,
1356 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1357 if(!rc)
1358 {
1359 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1360 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1361 }
1362 }
1363 return;
1364}
1365#endif
1366
1367void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1368{
1369 ENTER();
1370 switch ( pAdapter->device_mode )
1371 {
1372 case WLAN_HDD_INFRA_STATION:
1373 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001374 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001375 {
1376 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1377 {
1378 hdd_deinit_tx_rx( pAdapter );
1379 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1380 }
1381
1382 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1383 {
1384 hdd_wmm_adapter_close( pAdapter );
1385 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1386 }
1387
1388#ifdef CONFIG_CFG80211
1389 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1390#endif
1391
1392 break;
1393 }
1394
1395 case WLAN_HDD_SOFTAP:
1396 case WLAN_HDD_P2P_GO:
1397#ifdef WLAN_SOFTAP_FEATURE
1398 {
1399#ifdef CONFIG_CFG80211
1400 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1401#endif
1402
1403 hdd_unregister_hostapd(pAdapter);
1404 hdd_set_conparam( 0 );
1405#ifdef CONFIG_CFG80211
1406 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
1407#endif
1408 break;
1409 }
1410
1411 case WLAN_HDD_MONITOR:
1412 {
1413#ifdef CONFIG_CFG80211
1414 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
1415#endif
1416 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1417 {
1418 hdd_deinit_tx_rx( pAdapter );
1419 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1420 }
1421#ifdef CONFIG_CFG80211
1422 if(NULL != pAdapterforTx)
1423 {
1424 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
1425 }
1426#endif
1427#endif //WLAN_SOFTAP_FEATURE
1428 break;
1429 }
1430
1431
1432 default:
1433 break;
1434 }
1435
1436 EXIT();
1437}
1438
1439void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
1440{
1441 struct net_device *pWlanDev = pAdapter->dev;
1442
1443 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
1444 if( rtnl_held )
1445 {
1446 unregister_netdevice(pWlanDev);
1447 }
1448 else
1449 {
1450 unregister_netdev(pWlanDev);
1451 }
1452 // note that the pAdapter is no longer valid at this point
1453 // since the memory has been reclaimed
1454 }
1455
1456}
1457
1458VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
1459{
1460 VOS_STATUS status = VOS_STATUS_SUCCESS;
1461
1462 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
1463 {
1464 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1465 }
1466
1467 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
1468 {
1469 sme_StartAutoBmpsTimer(pHddCtx->hHal);
1470 }
1471
1472 if (pHddCtx->cfg_ini->fIsImpsEnabled)
1473 {
1474 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1475 }
1476
1477 return status;
1478}
1479
1480VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
1481{
1482 hdd_adapter_t *pAdapter = NULL;
1483 eHalStatus halStatus;
1484 VOS_STATUS status = VOS_STATUS_E_INVAL;
1485 v_BOOL_t disableBmps = FALSE;
1486 v_BOOL_t disableImps = FALSE;
1487
1488 switch(session_type)
1489 {
1490 case WLAN_HDD_INFRA_STATION:
1491 case WLAN_HDD_SOFTAP:
1492#ifdef WLAN_FEATURE_P2P
1493 case WLAN_HDD_P2P_CLIENT:
1494 case WLAN_HDD_P2P_GO:
1495#endif
1496 //Exit BMPS -> Is Sta/P2P Client is already connected
1497 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1498 if((NULL != pAdapter)&&
1499 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1500 {
1501 disableBmps = TRUE;
1502 }
1503
1504 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
1505 if((NULL != pAdapter)&&
1506 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1507 {
1508 disableBmps = TRUE;
1509 }
1510
1511 //Exit both Bmps and Imps incase of Go/SAP Mode
1512 if((WLAN_HDD_SOFTAP == session_type) ||
1513 (WLAN_HDD_P2P_GO == session_type))
1514 {
1515 disableBmps = TRUE;
1516 disableImps = TRUE;
1517 }
1518
1519 if(TRUE == disableImps)
1520 {
1521 if (pHddCtx->cfg_ini->fIsImpsEnabled)
1522 {
1523 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1524 }
1525 }
1526
1527 if(TRUE == disableBmps)
1528 {
1529 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
1530 {
1531 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1532
1533 if(eHAL_STATUS_SUCCESS != halStatus)
1534 {
1535 status = VOS_STATUS_E_FAILURE;
1536 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
1537 VOS_ASSERT(0);
1538 return status;
1539 }
1540 }
1541
1542 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
1543 {
1544 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
1545
1546 if(eHAL_STATUS_SUCCESS != halStatus)
1547 {
1548 status = VOS_STATUS_E_FAILURE;
1549 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
1550 VOS_ASSERT(0);
1551 return status;
1552 }
1553 }
1554 }
1555
1556 if((TRUE == disableBmps) ||
1557 (TRUE == disableImps))
1558 {
1559 /* Now, get the chip into Full Power now */
1560 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
1561 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
1562 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
1563
1564 if(halStatus != eHAL_STATUS_SUCCESS)
1565 {
1566 if(halStatus == eHAL_STATUS_PMC_PENDING)
1567 {
1568 //Block on a completion variable. Can't wait forever though
1569 wait_for_completion_interruptible_timeout(
1570 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
1571 }
1572 else
1573 {
1574 status = VOS_STATUS_E_FAILURE;
1575 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
1576 VOS_ASSERT(0);
1577 return status;
1578 }
1579 }
1580
1581 status = VOS_STATUS_SUCCESS;
1582 }
1583
1584 break;
1585 }
1586 return status;
1587}
1588
1589hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001590 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07001591 tANI_U8 rtnl_held )
1592{
1593 hdd_adapter_t *pAdapter = NULL;
1594 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
1595 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1596 VOS_STATUS exitbmpsStatus;
1597
1598 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
1599
1600 //Disable BMPS incase of Concurrency
1601 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
1602
1603 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
1604 {
1605 //Fail to Exit BMPS
1606 VOS_ASSERT(0);
1607 return NULL;
1608 }
1609
1610 switch(session_type)
1611 {
1612 case WLAN_HDD_INFRA_STATION:
1613#ifdef WLAN_FEATURE_P2P
1614 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001615 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001616#endif
1617 {
1618 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
1619
1620 if( NULL == pAdapter )
1621 return NULL;
1622
1623#ifdef CONFIG_CFG80211
Jeff Johnsone7245742012-09-05 17:12:55 -07001624 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
1625 NL80211_IFTYPE_P2P_CLIENT:
1626 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07001627#endif
1628
Jeff Johnson295189b2012-06-20 16:38:30 -07001629 pAdapter->device_mode = session_type;
1630
1631 status = hdd_init_station_mode( pAdapter );
1632 if( VOS_STATUS_SUCCESS != status )
1633 goto err_free_netdev;
1634
1635 status = hdd_register_interface( pAdapter, rtnl_held );
1636 if( VOS_STATUS_SUCCESS != status )
1637 {
1638 hdd_deinit_adapter(pHddCtx, pAdapter);
1639 goto err_free_netdev;
1640 }
1641 //Stop the Interface TX queue.
1642 netif_tx_disable(pAdapter->dev);
1643 //netif_tx_disable(pWlanDev);
1644 netif_carrier_off(pAdapter->dev);
1645
1646 break;
1647 }
1648
1649#ifdef WLAN_FEATURE_P2P
1650 case WLAN_HDD_P2P_GO:
1651#endif
1652 case WLAN_HDD_SOFTAP:
1653 {
1654 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
1655 if( NULL == pAdapter )
1656 return NULL;
1657
1658#ifdef CONFIG_CFG80211
1659 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
1660 NL80211_IFTYPE_AP:
1661 NL80211_IFTYPE_P2P_GO;
1662#endif
1663 pAdapter->device_mode = session_type;
1664
1665 status = hdd_init_ap_mode(pAdapter);
1666 if( VOS_STATUS_SUCCESS != status )
1667 goto err_free_netdev;
1668
1669 status = hdd_register_hostapd( pAdapter, rtnl_held );
1670 if( VOS_STATUS_SUCCESS != status )
1671 {
1672 hdd_deinit_adapter(pHddCtx, pAdapter);
1673 goto err_free_netdev;
1674 }
1675
1676 netif_tx_disable(pAdapter->dev);
1677 netif_carrier_off(pAdapter->dev);
1678
1679 hdd_set_conparam( 1 );
1680 break;
1681 }
1682 case WLAN_HDD_MONITOR:
1683 {
1684#ifdef CONFIG_CFG80211
1685 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
1686 if( NULL == pAdapter )
1687 return NULL;
1688
1689 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
1690 pAdapter->device_mode = session_type;
1691 status = hdd_register_interface( pAdapter, rtnl_held );
1692#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
1693 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
1694#else
1695 pAdapter->dev->open = hdd_mon_open;
1696 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
1697#endif
1698 hdd_init_tx_rx( pAdapter );
1699 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1700 //Set adapter to be used for data tx. It will use either GO or softap.
1701 pAdapter->sessionCtx.monitor.pAdapterForTx =
1702 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
1703#ifdef WLAN_FEATURE_P2P
1704 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
1705 {
1706 pAdapter->sessionCtx.monitor.pAdapterForTx =
1707 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
1708 }
1709#endif
1710 /* This workqueue will be used to transmit management packet over
1711 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07001712 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
1713 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
1714 return NULL;
1715 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07001716
Jeff Johnson295189b2012-06-20 16:38:30 -07001717 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
1718 hdd_mon_tx_work_queue);
1719#endif
1720 }
1721 break;
1722#ifdef ANI_MANF_DIAG
1723 case WLAN_HDD_FTM:
1724 {
1725 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
1726
1727 if( NULL == pAdapter )
1728 return NULL;
1729 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
1730 * message while loading driver in FTM mode. */
1731 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
1732 pAdapter->device_mode = session_type;
1733 status = hdd_register_interface( pAdapter, rtnl_held );
1734 }
1735 break;
1736#endif
1737 default:
1738 {
1739 VOS_ASSERT(0);
1740 return NULL;
1741 }
1742 }
1743
1744
1745 if( VOS_STATUS_SUCCESS == status )
1746 {
1747 //Add it to the hdd's session list.
1748 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
1749 if( NULL == pHddAdapterNode )
1750 {
1751 status = VOS_STATUS_E_NOMEM;
1752 }
1753 else
1754 {
1755 pHddAdapterNode->pAdapter = pAdapter;
1756 status = hdd_add_adapter_back ( pHddCtx,
1757 pHddAdapterNode );
1758 }
1759 }
1760
1761 if( VOS_STATUS_SUCCESS != status )
1762 {
1763 if( NULL != pAdapter )
1764 {
1765 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
1766 pAdapter = NULL;
1767 }
1768 if( NULL != pHddAdapterNode )
1769 {
1770 vos_mem_free( pHddAdapterNode );
1771 }
1772
1773 goto resume_bmps;
1774 }
1775
1776 if(VOS_STATUS_SUCCESS == status)
1777 {
1778 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
1779
1780#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1781 /* If there are concurrent session enable SW frame translation
1782 * for all registered STA
1783 * This is not required in case of PRIMA as HW frame translation
1784 * is disabled in PRIMA*/
1785 if (vos_concurrent_sessions_running())
1786 {
1787 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, TRUE);
1788 }
1789#endif
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07001790 //Initialize the WoWL service
1791 if(!hdd_init_wowl(pAdapter))
1792 {
1793 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
1794 goto err_free_netdev;
1795 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001796 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001797 return pAdapter;
1798
1799err_free_netdev:
1800 free_netdev(pAdapter->dev);
1801 wlan_hdd_release_intf_addr( pHddCtx,
1802 pAdapter->macAddressCurrent.bytes );
1803
1804resume_bmps:
1805 //If bmps disabled enable it
1806 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
1807 {
1808 hdd_enable_bmps_imps(pHddCtx);
1809 }
1810 return NULL;
1811}
1812
1813VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
1814 tANI_U8 rtnl_held )
1815{
1816 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
1817 VOS_STATUS status;
1818
1819 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
1820 if( VOS_STATUS_SUCCESS != status )
1821 return status;
1822
1823 while ( pCurrent->pAdapter != pAdapter )
1824 {
1825 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
1826 if( VOS_STATUS_SUCCESS != status )
1827 break;
1828
1829 pCurrent = pNext;
1830 }
1831 pAdapterNode = pCurrent;
1832 if( VOS_STATUS_SUCCESS == status )
1833 {
1834 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
1835 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
1836 hdd_remove_adapter( pHddCtx, pAdapterNode );
1837 vos_mem_free( pAdapterNode );
1838
1839#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1840 /* If there is no concurrent session disable SW frame translation
1841 * for all registered STA */
1842 /* This is not required in case of PRIMA as HW frame translation
1843 * is disabled in PRIMA*/
1844 if (!vos_concurrent_sessions_running())
1845 {
1846 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, FALSE);
1847 }
1848#endif
1849
1850 /* If there is a single session of STA/P2P client, re-enable BMPS */
1851 if ((!vos_concurrent_sessions_running()) &&
1852 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
1853 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
1854 {
1855 hdd_enable_bmps_imps(pHddCtx);
1856 }
1857
1858 return VOS_STATUS_SUCCESS;
1859 }
1860
1861 return VOS_STATUS_E_FAILURE;
1862}
1863
1864VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
1865{
1866 hdd_adapter_list_node_t *pHddAdapterNode;
1867 VOS_STATUS status;
1868
1869 ENTER();
1870
1871 do
1872 {
1873 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
1874 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
1875 {
1876 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
1877 vos_mem_free( pHddAdapterNode );
1878 }
1879 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
1880
1881 EXIT();
1882
1883 return VOS_STATUS_SUCCESS;
1884}
1885
1886void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
1887{
1888 v_U8_t addIE[1] = {0};
1889
1890 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1891 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
1892 eANI_BOOLEAN_FALSE) )
1893 {
1894 hddLog(LOGE,
1895 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
1896 }
1897
1898 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1899 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1900 eANI_BOOLEAN_FALSE) )
1901 {
1902 hddLog(LOGE,
1903 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1904 }
1905
1906 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1907 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1908 eANI_BOOLEAN_FALSE) )
1909 {
1910 hddLog(LOGE,
1911 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1912 }
1913}
1914
1915VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1916{
1917 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1918 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1919 union iwreq_data wrqu;
1920
1921 ENTER();
1922
1923 switch(pAdapter->device_mode)
1924 {
1925 case WLAN_HDD_INFRA_STATION:
1926 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001927 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001928 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
1929 {
1930 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
1931 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
1932 pAdapter->sessionId,
1933 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
1934 else
1935 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
1936 pAdapter->sessionId,
1937 eCSR_DISCONNECT_REASON_UNSPECIFIED);
1938 //success implies disconnect command got queued up successfully
1939 if(halStatus == eHAL_STATUS_SUCCESS)
1940 {
1941 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
1942 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
1943 }
1944 memset(&wrqu, '\0', sizeof(wrqu));
1945 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1946 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
1947 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
1948 }
1949 else
1950 {
1951 hdd_abort_mac_scan(pHddCtx);
1952 }
1953
1954 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1955 {
1956 INIT_COMPLETION(pAdapter->session_close_comp_var);
1957 if (eHAL_STATUS_SUCCESS ==
1958 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
1959 hdd_smeCloseSessionCallback, pAdapter))
1960 {
1961 //Block on a completion variable. Can't wait forever though.
1962 wait_for_completion_interruptible_timeout(
1963 &pAdapter->session_close_comp_var,
1964 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1965 }
1966 }
1967
1968 break;
1969
1970 case WLAN_HDD_SOFTAP:
1971 case WLAN_HDD_P2P_GO:
1972 //Any softap specific cleanup here...
1973 mutex_lock(&pHddCtx->sap_lock);
1974 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
1975 {
1976 VOS_STATUS status;
1977 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
1978
1979 //Stop Bss.
1980 status = WLANSAP_StopBss(pHddCtx->pvosContext);
1981 if (VOS_IS_STATUS_SUCCESS(status))
1982 {
1983 hdd_hostapd_state_t *pHostapdState =
1984 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
1985
1986 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
1987
1988 if (!VOS_IS_STATUS_SUCCESS(status))
1989 {
1990 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001991 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001992 }
1993 }
1994 else
1995 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001996 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001997 }
1998 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
1999
2000 if (eHAL_STATUS_FAILURE ==
2001 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2002 0, NULL, eANI_BOOLEAN_FALSE))
2003 {
2004 hddLog(LOGE,
2005 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002006 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002007 }
2008
2009 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2010 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2011 eANI_BOOLEAN_FALSE) )
2012 {
2013 hddLog(LOGE,
2014 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2015 }
2016
2017 // Reset WNI_CFG_PROBE_RSP Flags
2018 wlan_hdd_reset_prob_rspies(pAdapter);
2019 kfree(pAdapter->sessionCtx.ap.beacon);
2020 pAdapter->sessionCtx.ap.beacon = NULL;
2021 }
2022 mutex_unlock(&pHddCtx->sap_lock);
2023 break;
2024 case WLAN_HDD_MONITOR:
2025 break;
2026 default:
2027 break;
2028 }
2029
2030 EXIT();
2031 return VOS_STATUS_SUCCESS;
2032}
2033
2034VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2035{
2036 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2037 VOS_STATUS status;
2038 hdd_adapter_t *pAdapter;
2039
2040 ENTER();
2041
2042 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2043
2044 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2045 {
2046 pAdapter = pAdapterNode->pAdapter;
2047 netif_tx_disable(pAdapter->dev);
2048 netif_carrier_off(pAdapter->dev);
2049
2050 hdd_stop_adapter( pHddCtx, pAdapter );
2051
2052 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2053 pAdapterNode = pNext;
2054 }
2055
2056 EXIT();
2057
2058 return VOS_STATUS_SUCCESS;
2059}
2060
2061VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2062{
2063 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2064 VOS_STATUS status;
2065 hdd_adapter_t *pAdapter;
2066
2067 ENTER();
2068
2069 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2070
2071 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2072 {
2073 pAdapter = pAdapterNode->pAdapter;
2074 netif_tx_disable(pAdapter->dev);
2075 netif_carrier_off(pAdapter->dev);
2076
2077 //Record whether STA is associated
2078 pAdapter->sessionCtx.station.bSendDisconnect =
2079 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2080 VOS_TRUE : VOS_FALSE;
2081
2082 hdd_deinit_tx_rx(pAdapter);
2083 hdd_wmm_adapter_close(pAdapter);
2084
2085 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2086 pAdapterNode = pNext;
2087 }
2088
2089 EXIT();
2090
2091 return VOS_STATUS_SUCCESS;
2092}
2093
2094VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2095{
2096 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2097 VOS_STATUS status;
2098 hdd_adapter_t *pAdapter;
2099 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2100
2101 ENTER();
2102
2103 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2104
2105 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2106 {
2107 pAdapter = pAdapterNode->pAdapter;
2108
2109 switch(pAdapter->device_mode)
2110 {
2111 case WLAN_HDD_INFRA_STATION:
2112 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002113 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002114 hdd_init_station_mode(pAdapter);
2115 /* Open the gates for HDD to receive Wext commands */
2116 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002117 pHddCtx->scan_info.mScanPending = FALSE;
2118 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002119
2120 //Trigger the initial scan
2121 hdd_wlan_initial_scan(pAdapter);
2122
2123 //Indicate disconnect event to supplicant if associated previously
2124 if(pAdapter->sessionCtx.station.bSendDisconnect)
2125 {
2126 union iwreq_data wrqu;
2127 memset(&wrqu, '\0', sizeof(wrqu));
2128 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2129 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2130 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2131 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2132
2133#ifdef CONFIG_CFG80211
2134 /* indicate disconnected event to nl80211 */
2135 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2136 NULL, 0, GFP_KERNEL);
2137#endif
2138 }
2139 break;
2140
2141 case WLAN_HDD_SOFTAP:
2142 /* softAP can handle SSR */
2143 break;
2144
2145 case WLAN_HDD_P2P_GO:
2146#ifdef CONFIG_CFG80211
2147 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2148 __func__);
2149 /* event supplicant to restart */
2150 cfg80211_del_sta(pAdapter->dev,
2151 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
2152#endif
2153 break;
2154
2155 case WLAN_HDD_MONITOR:
2156 /* monitor interface start */
2157 break;
2158 default:
2159 break;
2160 }
2161
2162 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2163 pAdapterNode = pNext;
2164 }
2165
2166 EXIT();
2167
2168 return VOS_STATUS_SUCCESS;
2169}
2170
2171VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2172{
2173 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2174 hdd_adapter_t *pAdapter;
2175 VOS_STATUS status;
2176 v_U32_t roamId;
2177
2178 ENTER();
2179
2180 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2181
2182 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2183 {
2184 pAdapter = pAdapterNode->pAdapter;
2185
2186 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2187 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2188 {
2189 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2190 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2191
2192 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2193 init_completion(&pAdapter->disconnect_comp_var);
2194 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2195 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2196
2197 wait_for_completion_interruptible_timeout(
2198 &pAdapter->disconnect_comp_var,
2199 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2200
2201 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2202 pHddCtx->isAmpAllowed = VOS_FALSE;
2203 sme_RoamConnect(pHddCtx->hHal,
2204 pAdapter->sessionId, &(pWextState->roamProfile),
2205 &roamId);
2206 }
2207
2208 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2209 pAdapterNode = pNext;
2210 }
2211
2212 EXIT();
2213
2214 return VOS_STATUS_SUCCESS;
2215}
2216
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002217bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002218{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002219 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002220}
2221
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002222/* Once SSR is disabled then it cannot be set. */
2223void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002224{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002225 if (HDD_SSR_DISABLED == isSsrRequired)
2226 return;
2227
Jeff Johnson295189b2012-06-20 16:38:30 -07002228 isSsrRequired = value;
2229}
2230
2231VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2232 hdd_adapter_list_node_t** ppAdapterNode)
2233{
2234 VOS_STATUS status;
2235 spin_lock(&pHddCtx->hddAdapters.lock);
2236 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2237 (hdd_list_node_t**) ppAdapterNode );
2238 spin_unlock(&pHddCtx->hddAdapters.lock);
2239 return status;
2240}
2241
2242VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2243 hdd_adapter_list_node_t* pAdapterNode,
2244 hdd_adapter_list_node_t** pNextAdapterNode)
2245{
2246 VOS_STATUS status;
2247 spin_lock(&pHddCtx->hddAdapters.lock);
2248 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2249 (hdd_list_node_t*) pAdapterNode,
2250 (hdd_list_node_t**)pNextAdapterNode );
2251
2252 spin_unlock(&pHddCtx->hddAdapters.lock);
2253 return status;
2254}
2255
2256VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2257 hdd_adapter_list_node_t* pAdapterNode)
2258{
2259 VOS_STATUS status;
2260 spin_lock(&pHddCtx->hddAdapters.lock);
2261 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2262 &pAdapterNode->node );
2263 spin_unlock(&pHddCtx->hddAdapters.lock);
2264 return status;
2265}
2266
2267VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2268 hdd_adapter_list_node_t** ppAdapterNode)
2269{
2270 VOS_STATUS status;
2271 spin_lock(&pHddCtx->hddAdapters.lock);
2272 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2273 (hdd_list_node_t**) ppAdapterNode );
2274 spin_unlock(&pHddCtx->hddAdapters.lock);
2275 return status;
2276}
2277
2278VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2279 hdd_adapter_list_node_t* pAdapterNode)
2280{
2281 VOS_STATUS status;
2282 spin_lock(&pHddCtx->hddAdapters.lock);
2283 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2284 (hdd_list_node_t*) pAdapterNode );
2285 spin_unlock(&pHddCtx->hddAdapters.lock);
2286 return status;
2287}
2288
2289VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2290 hdd_adapter_list_node_t* pAdapterNode)
2291{
2292 VOS_STATUS status;
2293 spin_lock(&pHddCtx->hddAdapters.lock);
2294 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2295 (hdd_list_node_t*) pAdapterNode );
2296 spin_unlock(&pHddCtx->hddAdapters.lock);
2297 return status;
2298}
2299
2300hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2301 tSirMacAddr macAddr )
2302{
2303 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2304 hdd_adapter_t *pAdapter;
2305 VOS_STATUS status;
2306
2307 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2308
2309 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2310 {
2311 pAdapter = pAdapterNode->pAdapter;
2312
2313 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2314 macAddr, sizeof(tSirMacAddr) ) )
2315 {
2316 return pAdapter;
2317 }
2318 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2319 pAdapterNode = pNext;
2320 }
2321
2322 return NULL;
2323
2324}
2325
2326hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2327{
2328 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2329 hdd_adapter_t *pAdapter;
2330 VOS_STATUS status;
2331
2332 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2333
2334 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2335 {
2336 pAdapter = pAdapterNode->pAdapter;
2337
2338 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2339 IFNAMSIZ ) )
2340 {
2341 return pAdapter;
2342 }
2343 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2344 pAdapterNode = pNext;
2345 }
2346
2347 return NULL;
2348
2349}
2350
2351hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
2352{
2353 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2354 hdd_adapter_t *pAdapter;
2355 VOS_STATUS status;
2356
2357 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2358
2359 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2360 {
2361 pAdapter = pAdapterNode->pAdapter;
2362
2363 if( pAdapter && (mode == pAdapter->device_mode) )
2364 {
2365 return pAdapter;
2366 }
2367 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2368 pAdapterNode = pNext;
2369 }
2370
2371 return NULL;
2372
2373}
2374
2375//Remove this function later
2376hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
2377{
2378 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2379 hdd_adapter_t *pAdapter;
2380 VOS_STATUS status;
2381
2382 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2383
2384 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2385 {
2386 pAdapter = pAdapterNode->pAdapter;
2387
2388 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
2389 {
2390 return pAdapter;
2391 }
2392
2393 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2394 pAdapterNode = pNext;
2395 }
2396
2397 return NULL;
2398
2399}
2400
2401#ifdef CONFIG_CFG80211
2402/**---------------------------------------------------------------------------
2403
2404 \brief hdd_set_monitor_tx_adapter() -
2405
2406 This API initializes the adapter to be used while transmitting on monitor
2407 adapter.
2408
2409 \param - pHddCtx - Pointer to the HDD context.
2410 pAdapter - Adapter that will used for TX. This can be NULL.
2411 \return - None.
2412 --------------------------------------------------------------------------*/
2413void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2414{
2415 hdd_adapter_t *pMonAdapter;
2416
2417 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
2418
2419 if( NULL != pMonAdapter )
2420 {
2421 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
2422 }
2423}
2424#endif
2425/**---------------------------------------------------------------------------
2426
2427 \brief hdd_select_queue() -
2428
2429 This API returns the operating channel of the requested device mode
2430
2431 \param - pHddCtx - Pointer to the HDD context.
2432 - mode - Device mode for which operating channel is required
2433 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
2434 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
2435 \return - channel number. "0" id the requested device is not found OR it is not connected.
2436 --------------------------------------------------------------------------*/
2437v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
2438{
2439 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2440 VOS_STATUS status;
2441 hdd_adapter_t *pAdapter;
2442 v_U8_t operatingChannel = 0;
2443
2444 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2445
2446 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2447 {
2448 pAdapter = pAdapterNode->pAdapter;
2449
2450 if( mode == pAdapter->device_mode )
2451 {
2452 switch(pAdapter->device_mode)
2453 {
2454 case WLAN_HDD_INFRA_STATION:
2455 case WLAN_HDD_P2P_CLIENT:
2456 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2457 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
2458 break;
2459 case WLAN_HDD_SOFTAP:
2460 case WLAN_HDD_P2P_GO:
2461 /*softap connection info */
2462 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2463 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
2464 break;
2465 default:
2466 break;
2467 }
2468
2469 break; //Found the device of interest. break the loop
2470 }
2471
2472 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2473 pAdapterNode = pNext;
2474 }
2475 return operatingChannel;
2476}
2477
2478#ifdef WLAN_FEATURE_PACKET_FILTERING
2479/**---------------------------------------------------------------------------
2480
2481 \brief hdd_set_multicast_list() -
2482
2483 This used to set the multicast address list.
2484
2485 \param - dev - Pointer to the WLAN device.
2486 - skb - Pointer to OS packet (sk_buff).
2487 \return - success/fail
2488
2489 --------------------------------------------------------------------------*/
2490static void hdd_set_multicast_list(struct net_device *dev)
2491{
2492 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2493 hdd_context_t *pHddCtx;
2494 int mc_count;
2495 int i = 0;
2496 struct netdev_hw_addr *ha;
2497 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2498 if (NULL == pHddCtx)
2499 {
2500 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002501 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002502 return;
2503 }
2504
2505 if (dev->flags & IFF_ALLMULTI)
2506 {
2507 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002508 "%s: allow all multicast frames", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002509 pHddCtx->mc_addr_list.mc_cnt = 0;
2510 }
2511 else
2512 {
2513 mc_count = netdev_mc_count(dev);
2514 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002515 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07002516 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
2517 {
2518 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002519 "%s: No free filter available; allow all multicast frames", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002520 pHddCtx->mc_addr_list.mc_cnt = 0;
2521 return;
2522 }
2523
2524 pHddCtx->mc_addr_list.mc_cnt = mc_count;
2525
2526 netdev_for_each_mc_addr(ha, dev) {
2527 if (i == mc_count)
2528 break;
2529 memset(&(pHddCtx->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
2530 memcpy(&(pHddCtx->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
2531 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = %02x:%02x:%02x:%02x:%02x:%02x",
2532 __func__, i,
2533 pHddCtx->mc_addr_list.addr[i][0], pHddCtx->mc_addr_list.addr[i][1],
2534 pHddCtx->mc_addr_list.addr[i][2], pHddCtx->mc_addr_list.addr[i][3],
2535 pHddCtx->mc_addr_list.addr[i][4], pHddCtx->mc_addr_list.addr[i][5]);
2536 i++;
2537 }
2538 }
2539 return;
2540}
2541#endif
2542
2543/**---------------------------------------------------------------------------
2544
2545 \brief hdd_select_queue() -
2546
2547 This function is registered with the Linux OS for network
2548 core to decide which queue to use first.
2549
2550 \param - dev - Pointer to the WLAN device.
2551 - skb - Pointer to OS packet (sk_buff).
2552 \return - ac, Queue Index/access category corresponding to UP in IP header
2553
2554 --------------------------------------------------------------------------*/
2555v_U16_t hdd_select_queue(struct net_device *dev,
2556 struct sk_buff *skb)
2557{
2558 return hdd_wmm_select_queue(dev, skb);
2559}
2560
2561
2562/**---------------------------------------------------------------------------
2563
2564 \brief hdd_wlan_initial_scan() -
2565
2566 This function triggers the initial scan
2567
2568 \param - pAdapter - Pointer to the HDD adapter.
2569
2570 --------------------------------------------------------------------------*/
2571void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
2572{
2573 tCsrScanRequest scanReq;
2574 tCsrChannelInfo channelInfo;
2575 eHalStatus halStatus;
2576 unsigned long scanId;
2577 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2578
2579 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
2580 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
2581 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
2582
2583 if(sme_Is11dSupported(pHddCtx->hHal))
2584 {
2585 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
2586 if ( HAL_STATUS_SUCCESS( halStatus ) )
2587 {
2588 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
2589 if( !scanReq.ChannelInfo.ChannelList )
2590 {
2591 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
2592 vos_mem_free(channelInfo.ChannelList);
2593 return;
2594 }
2595 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
2596 channelInfo.numOfChannels);
2597 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
2598 vos_mem_free(channelInfo.ChannelList);
2599 }
2600
2601 scanReq.scanType = eSIR_PASSIVE_SCAN;
2602 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
2603 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
2604 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
2605 }
2606 else
2607 {
2608 scanReq.scanType = eSIR_ACTIVE_SCAN;
2609 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
2610 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
2611 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
2612 }
2613
2614 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
2615 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2616 {
2617 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
2618 __func__, halStatus );
2619 }
2620
2621 if(sme_Is11dSupported(pHddCtx->hHal))
2622 vos_mem_free(scanReq.ChannelInfo.ChannelList);
2623}
2624
2625struct fullPowerContext
2626{
2627 struct completion completion;
2628 unsigned int magic;
2629};
2630#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
2631
2632/**---------------------------------------------------------------------------
2633
2634 \brief hdd_full_power_callback() - HDD full power callback function
2635
2636 This is the function invoked by SME to inform the result of a full power
2637 request issued by HDD
2638
2639 \param - callbackcontext - Pointer to cookie
2640 \param - status - result of request
2641
2642 \return - None
2643
2644 --------------------------------------------------------------------------*/
2645static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
2646{
2647 struct fullPowerContext *pContext = callbackContext;
2648
2649 hddLog(VOS_TRACE_LEVEL_INFO,
2650 "%s: context = %p, status = %d", pContext, status);
2651
2652 if (NULL == callbackContext)
2653 {
2654 hddLog(VOS_TRACE_LEVEL_ERROR,
2655 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002656 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002657 return;
2658 }
2659
2660 /* there is a race condition that exists between this callback function
2661 and the caller since the caller could time out either before or
2662 while this code is executing. we'll assume the timeout hasn't
2663 occurred, but we'll verify that right before we save our work */
2664
2665 if (POWER_CONTEXT_MAGIC != pContext->magic)
2666 {
2667 /* the caller presumably timed out so there is nothing we can do */
2668 hddLog(VOS_TRACE_LEVEL_WARN,
2669 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002670 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07002671 return;
2672 }
2673
2674 /* the race is on. caller could have timed out immediately after
2675 we verified the magic, but if so, caller will wait a short time
2676 for us to notify the caller, so the context will stay valid */
2677 complete(&pContext->completion);
2678}
2679
2680/**---------------------------------------------------------------------------
2681
2682 \brief hdd_wlan_exit() - HDD WLAN exit function
2683
2684 This is the driver exit point (invoked during rmmod)
2685
2686 \param - pHddCtx - Pointer to the HDD Context
2687
2688 \return - None
2689
2690 --------------------------------------------------------------------------*/
2691void hdd_wlan_exit(hdd_context_t *pHddCtx)
2692{
2693 eHalStatus halStatus;
2694 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
2695 VOS_STATUS vosStatus;
2696#ifdef ANI_BUS_TYPE_SDIO
2697 struct sdio_func *sdio_func_dev = NULL;
2698#endif // ANI_BUS_TYPE_SDIO
2699#ifdef CONFIG_CFG80211
2700 struct wiphy *wiphy = pHddCtx->wiphy;
2701#endif
2702#ifdef FEATURE_WLAN_INTEGRATED_SOC
2703 hdd_adapter_t* pAdapter;
2704#endif
2705 struct fullPowerContext powerContext;
2706 long lrc;
2707
2708 ENTER();
2709
Ng Chilam1322ea32012-12-27 17:33:08 -08002710#ifdef ANI_MANF_DIAG
2711 if (VOS_FTM_MODE != hdd_get_conparam())
2712#endif /* ANI_MANF_DIAG */
2713 {
2714 // Unloading, restart logic is no more required.
2715 wlan_hdd_restart_deinit(pHddCtx);
2716 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002717
Jeff Johnson295189b2012-06-20 16:38:30 -07002718#ifdef CONFIG_CFG80211
2719#ifdef WLAN_SOFTAP_FEATURE
2720 if (VOS_STA_SAP_MODE != hdd_get_conparam())
2721#endif
2722 {
2723#ifdef ANI_MANF_DIAG
2724 if (VOS_FTM_MODE != hdd_get_conparam())
2725#endif /* ANI_MANF_DIAG */
2726 {
2727 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
2728 WLAN_HDD_INFRA_STATION);
2729 if (pAdapter == NULL)
2730 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2731
2732 if (pAdapter != NULL)
2733 {
2734 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
2735 hdd_UnregisterWext(pAdapter->dev);
2736 }
2737 }
2738 }
2739#endif
2740
2741#ifdef ANI_MANF_DIAG
2742 if (VOS_FTM_MODE == hdd_get_conparam())
2743 {
2744 wlan_hdd_ftm_close(pHddCtx);
2745 goto free_hdd_ctx;
2746 }
2747#endif
2748 //Stop the Interface TX queue.
2749 //netif_tx_disable(pWlanDev);
2750 //netif_carrier_off(pWlanDev);
2751
2752#ifdef CONFIG_HAS_EARLYSUSPEND
2753 // unregister suspend/resume callbacks
2754 if(pHddCtx->cfg_ini->nEnableSuspend)
2755 {
2756 unregister_wlan_suspend();
2757 }
2758#endif
2759
2760#ifdef FEATURE_WLAN_INTEGRATED_SOC
2761#ifdef WLAN_SOFTAP_FEATURE
2762 if (VOS_STA_SAP_MODE == hdd_get_conparam())
2763 {
2764 pAdapter = hdd_get_adapter(pHddCtx,
2765 WLAN_HDD_SOFTAP);
2766 }
2767 else
2768 {
2769#endif
2770#ifdef ANI_MANF_DIAG
2771 if (VOS_FTM_MODE != hdd_get_conparam())
2772#endif /* ANI_MANF_DIAG */
2773 {
2774 pAdapter = hdd_get_adapter(pHddCtx,
2775 WLAN_HDD_INFRA_STATION);
2776 }
2777#ifdef WLAN_SOFTAP_FEATURE
2778 }
2779#endif
2780 /* DeRegister with platform driver as client for Suspend/Resume */
2781 vosStatus = hddDeregisterPmOps(pHddCtx);
2782 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2783 {
2784 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
2785 VOS_ASSERT(0);
2786 }
2787
2788 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
2789 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2790 {
2791 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
2792 }
2793#endif //FEATURE_WLAN_INTEGRATED_SOC
2794
Chilam NG571c65a2013-01-19 12:27:36 +05302795#ifdef FEATURE_WLAN_TDLS
2796 wlan_hdd_tdls_exit();
2797#endif
2798
Jeff Johnson295189b2012-06-20 16:38:30 -07002799 // Cancel any outstanding scan requests. We are about to close all
2800 // of our adapters, but an adapter structure is what SME passes back
2801 // to our callback function. Hence if there are any outstanding scan
2802 // requests then there is a race condition between when the adapter
2803 // is closed and when the callback is invoked. We try to resolve that
2804 // race condition here by canceling any outstanding scans before we
2805 // close the adapters.
2806 // Note that the scans may be cancelled in an asynchronous manner, so
2807 // ideally there needs to be some kind of synchronization. Rather than
2808 // introduce a new synchronization here, we will utilize the fact that
2809 // we are about to Request Full Power, and since that is synchronized,
2810 // the expectation is that by the time Request Full Power has completed,
2811 // all scans will be cancelled.
2812 hdd_abort_mac_scan( pHddCtx );
2813
2814 //Disable IMPS/BMPS as we do not want the device to enter any power
2815 //save mode during shutdown
2816 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2817 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2818 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
2819
2820 //Ensure that device is in full power as we will touch H/W during vos_Stop
2821 init_completion(&powerContext.completion);
2822 powerContext.magic = POWER_CONTEXT_MAGIC;
2823
2824 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
2825 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
2826
2827 if (eHAL_STATUS_SUCCESS != halStatus)
2828 {
2829 if (eHAL_STATUS_PMC_PENDING == halStatus)
2830 {
2831 /* request was sent -- wait for the response */
2832 lrc = wait_for_completion_interruptible_timeout(
2833 &powerContext.completion,
2834 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
2835 /* either we have a response or we timed out
2836 either way, first invalidate our magic */
2837 powerContext.magic = 0;
2838 if (lrc <= 0)
2839 {
2840 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002841 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07002842 /* there is a race condition such that the callback
2843 function could be executing at the same time we are. of
2844 primary concern is if the callback function had already
2845 verified the "magic" but hasn't yet set the completion
2846 variable. Since the completion variable is on our
2847 stack, we'll delay just a bit to make sure the data is
2848 still valid if that is the case */
2849 msleep(50);
2850 }
2851 }
2852 else
2853 {
2854 hddLog(VOS_TRACE_LEVEL_ERROR,
2855 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002856 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07002857 VOS_ASSERT(0);
2858 /* continue -- need to clean up as much as possible */
2859 }
2860 }
2861
2862 // Unregister the Net Device Notifier
2863 unregister_netdevice_notifier(&hdd_netdev_notifier);
2864
Jeff Johnson295189b2012-06-20 16:38:30 -07002865 hdd_stop_all_adapters( pHddCtx );
2866
2867#ifdef ANI_BUS_TYPE_SDIO
2868 sdio_func_dev = libra_getsdio_funcdev();
2869
2870 if(sdio_func_dev == NULL)
2871 {
2872 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
2873 VOS_ASSERT(0);
2874 return;
2875 }
2876
2877 sd_claim_host(sdio_func_dev);
2878
2879 /* Disable SDIO IRQ since we are exiting */
2880 libra_enable_sdio_irq(sdio_func_dev, 0);
2881
2882 sd_release_host(sdio_func_dev);
2883#endif // ANI_BUS_TYPE_SDIO
2884
2885#ifdef WLAN_BTAMP_FEATURE
2886 vosStatus = WLANBAP_Stop(pVosContext);
2887 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2888 {
2889 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2890 "%s: Failed to stop BAP",__func__);
2891 }
2892#endif //WLAN_BTAMP_FEATURE
2893
2894 //Stop all the modules
2895 vosStatus = vos_stop( pVosContext );
2896 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2897 {
2898 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2899 "%s: Failed to stop VOSS",__func__);
2900 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2901 }
2902
2903#ifdef ANI_BUS_TYPE_SDIO
2904 vosStatus = WLANBAL_Stop( pVosContext );
2905
2906 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN BAL STOP\n");
2907 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2908 {
2909 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2910 "%s: Failed to stop BAL",__func__);
2911 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2912 }
2913
2914 msleep(50);
2915 //Put the chip is standby before asserting deep sleep
2916 vosStatus = WLANBAL_SuspendChip( pVosContext );
2917
2918 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN Suspend Chip\n");
2919
2920 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2921 {
2922 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2923 "%s: Failed to suspend chip ",__func__);
2924 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2925 }
2926 //Invoke SAL stop
2927 vosStatus = WLANSAL_Stop( pVosContext );
2928 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2929 {
2930 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2931 "%s: Failed to stop SAL",__func__);
2932 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2933 }
2934
2935#endif // ANI_BUS_TYPE_SDIO
2936
2937 //Assert Deep sleep signal now to put Libra HW in lowest power state
2938 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
2939 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2940
2941 //Vote off any PMIC voltage supplies
2942 vos_chipPowerDown(NULL, NULL, NULL);
2943
2944 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
2945
2946 //Clean up HDD Nlink Service
2947 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2948 nl_srv_exit();
2949
2950 //This requires pMac access, Call this before vos_close().
2951#ifdef CONFIG_HAS_EARLYSUSPEND
2952 hdd_unregister_mcast_bcast_filter(pHddCtx);
2953#endif
2954
2955 //Close the scheduler before calling vos_close to make sure no thread is
2956 // scheduled after the each module close is called i.e after all the data
2957 // structures are freed.
2958 vosStatus = vos_sched_close( pVosContext );
2959 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
2960 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2961 "%s: Failed to close VOSS Scheduler",__func__);
2962 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2963 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002964
2965#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2966 /* Destroy the wake lock */
2967 wake_lock_destroy(&pHddCtx->rx_wake_lock);
2968#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08002969 /* Destroy the wake lock */
2970 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07002971
2972 //Close VOSS
2973 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
2974 vos_close(pVosContext);
2975
2976#ifdef ANI_BUS_TYPE_SDIO
2977 vosStatus = WLANBAL_Close(pVosContext);
2978 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2979 {
2980 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2981 "%s: Failed to close BAL",__func__);
2982 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2983 }
2984 hddLog(VOS_TRACE_LEVEL_ERROR,"Returned WLAN BAL CLOSE\n\n\n\n");
2985#endif // ANI_BUS_TYPE_SDIO
2986
2987 //Close Watchdog
2988 if(pHddCtx->cfg_ini->fIsLogpEnabled)
2989 vos_watchdog_close(pVosContext);
2990
2991 /* Cancel the vote for XO Core ON.
2992 * This is done here to ensure there is no race condition since MC, TX and WD threads have
2993 * exited at this point
2994 */
2995 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
2996 " when WLAN is turned OFF\n");
2997 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
2998 {
2999 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3000 " Not returning failure."
3001 " Power consumed will be high\n");
3002 }
3003
3004 hdd_close_all_adapters( pHddCtx );
3005
3006
3007 //Free up dynamically allocated members inside HDD Adapter
3008 kfree(pHddCtx->cfg_ini);
3009 pHddCtx->cfg_ini= NULL;
3010
3011 /* free the power on lock from platform driver */
3012 if (free_riva_power_on_lock("wlan"))
3013 {
3014 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3015 __func__);
3016 }
3017
3018#ifdef ANI_MANF_DIAG
3019free_hdd_ctx:
3020#endif
3021#ifdef CONFIG_CFG80211
3022 wiphy_unregister(wiphy) ;
3023 wiphy_free(wiphy) ;
3024#else
3025 vos_mem_free( pHddCtx );
3026#endif
3027 if (hdd_is_ssr_required())
3028 {
3029 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003030 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003031 msleep(5000);
3032 }
3033 hdd_set_ssr_required (VOS_FALSE);
3034}
3035
3036
3037/**---------------------------------------------------------------------------
3038
3039 \brief hdd_update_config_from_nv() - Function to update the contents of
3040 the running configuration with parameters taken from NV storage
3041
3042 \param - pHddCtx - Pointer to the HDD global context
3043
3044 \return - VOS_STATUS_SUCCESS if successful
3045
3046 --------------------------------------------------------------------------*/
3047static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3048{
3049#ifndef FEATURE_WLAN_INTEGRATED_SOC
3050 eHalStatus halStatus;
3051#endif
3052
3053#ifdef FEATURE_WLAN_INTEGRATED_SOC
3054 v_BOOL_t itemIsValid = VOS_FALSE;
3055 VOS_STATUS status;
3056 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3057 v_U8_t macLoop;
3058
3059 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3060 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3061 if(status != VOS_STATUS_SUCCESS)
3062 {
3063 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3064 return VOS_STATUS_E_FAILURE;
3065 }
3066
3067 if (itemIsValid == VOS_TRUE)
3068 {
3069 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3070 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3071 VOS_MAX_CONCURRENCY_PERSONA);
3072 if(status != VOS_STATUS_SUCCESS)
3073 {
3074 /* Get MAC from NV fail, not update CFG info
3075 * INI MAC value will be used for MAC setting */
3076 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3077 return VOS_STATUS_E_FAILURE;
3078 }
3079
3080 /* If first MAC is not valid, treat all others are not valid
3081 * Then all MACs will be got from ini file */
3082 if(vos_is_macaddr_zero(&macFromNV[0]))
3083 {
3084 /* MAC address in NV file is not configured yet */
3085 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3086 return VOS_STATUS_E_INVAL;
3087 }
3088
3089 /* Get MAC address from NV, update CFG info */
3090 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3091 {
3092 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3093 {
3094 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3095 /* This MAC is not valid, skip it
3096 * This MAC will be got from ini file */
3097 }
3098 else
3099 {
3100 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3101 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3102 VOS_MAC_ADDR_SIZE);
3103 }
3104 }
3105 }
3106 else
3107 {
3108 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3109 return VOS_STATUS_E_FAILURE;
3110 }
3111#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3112
3113#ifndef FEATURE_WLAN_INTEGRATED_SOC
3114#if 1 /* need to fix for concurrency */
3115 // Set the MAC Address
3116 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3117 halStatus = ccmCfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3118 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3119 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]),
3120 hdd_set_mac_addr_cb, VOS_FALSE );
3121
3122 if (!HAL_STATUS_SUCCESS( halStatus ))
3123 {
3124 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3125 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
3126 return VOS_STATUS_E_FAILURE;
3127 }
3128#endif
3129#endif
3130
3131 return VOS_STATUS_SUCCESS;
3132}
3133
3134/**---------------------------------------------------------------------------
3135
3136 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3137
3138 \param - pAdapter - Pointer to the HDD
3139
3140 \return - None
3141
3142 --------------------------------------------------------------------------*/
3143VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3144{
3145 eHalStatus halStatus;
3146 v_U32_t listenInterval;
3147
3148#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
3149 /* In the non-integrated architecture we update the configuration from
3150 the INI file and from NV after vOSS has been started
3151 */
3152
3153 // Apply the cfg.ini to cfg.dat
3154 if (FALSE == hdd_update_config_dat(pHddCtx))
3155 {
3156 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3157 return VOS_STATUS_E_FAILURE;
3158 }
3159
3160 // Apply the NV to cfg.dat
3161 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3162 {
3163 hddLog(VOS_TRACE_LEVEL_FATAL,
3164 "%s: config update from NV failed", __func__ );
3165 return VOS_STATUS_E_FAILURE;
3166 }
3167#endif // FEATURE_WLAN_NON_INTEGRATED_SOC
3168
3169 // Send ready indication to the HDD. This will kick off the MAC
3170 // into a 'running' state and should kick off an initial scan.
3171 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3172 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3173 {
3174 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3175 "code %08d [x%08x]",__func__, halStatus, halStatus );
3176 return VOS_STATUS_E_FAILURE;
3177 }
3178
3179 // Set default LI into HDD context,
3180 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3181 // And RIVA will crash
3182 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3183 pHddCtx->hdd_actual_LI_value = listenInterval;
3184
3185 return VOS_STATUS_SUCCESS;
3186}
3187
3188#ifdef ANI_BUS_TYPE_SDIO
3189
3190#ifndef ANI_MANF_DIAG
3191// Routine to initialize the PMU
3192void wlan_hdd_enable_deepsleep(v_VOID_t * pVosContext)
3193{
3194/*-------------- Need to fix this correctly while doing Deepsleep testing
3195 tANI_U32 regValue = 0;
3196
3197 regValue = QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_DEEP_SLEEP_EN_MASK |
3198 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_AON_MASK_MASK |
3199 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_SW_MASK_MASK |
3200 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_2P3_LPM_MASK_MASK;
3201
3202 WLANBAL_WriteRegister(pVosContext, QWLAN_PMU_LDO_CTRL_REG_REG, regValue);
3203---------------------*/
3204
3205 return;
3206}
3207#endif
3208#endif
3209
3210/* wake lock APIs for HDD */
3211void hdd_prevent_suspend(void)
3212{
Jeff Johnsone7245742012-09-05 17:12:55 -07003213#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07003214 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003215#else
3216 wcnss_prevent_suspend();
3217#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003218}
3219
3220void hdd_allow_suspend(void)
3221{
Jeff Johnsone7245742012-09-05 17:12:55 -07003222#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07003223 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003224#else
3225 wcnss_allow_suspend();
3226#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003227}
3228
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003229void hdd_allow_suspend_timeout(v_U32_t timeout)
3230{
3231#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
3232 wake_lock_timeout(&wlan_wake_lock, timeout);
3233#else
3234 /* Do nothing as there is no API in wcnss for timeout*/
3235#endif
3236}
3237
Jeff Johnson295189b2012-06-20 16:38:30 -07003238/**---------------------------------------------------------------------------
3239
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003240 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3241 information between Host and Riva
3242
3243 This function gets reported version of FW
3244 It also finds the version of Riva headers used to compile the host
3245 It compares the above two and prints a warning if they are different
3246 It gets the SW and HW version string
3247 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3248 indicating the features they support through a bitmap
3249
3250 \param - pHddCtx - Pointer to HDD context
3251
3252 \return - void
3253
3254 --------------------------------------------------------------------------*/
3255
3256void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3257{
3258
3259 tSirVersionType versionCompiled;
3260 tSirVersionType versionReported;
3261 tSirVersionString versionString;
3262 tANI_U8 fwFeatCapsMsgSupported = 0;
3263 VOS_STATUS vstatus;
3264
3265 /* retrieve and display WCNSS version information */
3266 do {
3267
3268 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3269 &versionCompiled);
3270 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3271 {
3272 hddLog(VOS_TRACE_LEVEL_FATAL,
3273 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003274 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003275 break;
3276 }
3277
3278 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3279 &versionReported);
3280 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3281 {
3282 hddLog(VOS_TRACE_LEVEL_FATAL,
3283 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003284 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003285 break;
3286 }
3287
3288 if ((versionCompiled.major != versionReported.major) ||
3289 (versionCompiled.minor != versionReported.minor) ||
3290 (versionCompiled.version != versionReported.version) ||
3291 (versionCompiled.revision != versionReported.revision))
3292 {
3293 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3294 "Host expected %u.%u.%u.%u\n",
3295 WLAN_MODULE_NAME,
3296 (int)versionReported.major,
3297 (int)versionReported.minor,
3298 (int)versionReported.version,
3299 (int)versionReported.revision,
3300 (int)versionCompiled.major,
3301 (int)versionCompiled.minor,
3302 (int)versionCompiled.version,
3303 (int)versionCompiled.revision);
3304 }
3305 else
3306 {
3307 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3308 WLAN_MODULE_NAME,
3309 (int)versionReported.major,
3310 (int)versionReported.minor,
3311 (int)versionReported.version,
3312 (int)versionReported.revision);
3313 }
3314
3315 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3316 versionString,
3317 sizeof(versionString));
3318 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3319 {
3320 hddLog(VOS_TRACE_LEVEL_FATAL,
3321 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003322 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003323 break;
3324 }
3325
3326 pr_info("%s: WCNSS software version %s\n",
3327 WLAN_MODULE_NAME, versionString);
3328
3329 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3330 versionString,
3331 sizeof(versionString));
3332 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3333 {
3334 hddLog(VOS_TRACE_LEVEL_FATAL,
3335 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003336 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003337 break;
3338 }
3339
3340 pr_info("%s: WCNSS hardware version %s\n",
3341 WLAN_MODULE_NAME, versionString);
3342
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003343 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3344 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003345 send the message only if it the riva is 1.1
3346 minor numbers for different riva branches:
3347 0 -> (1.0)Mainline Build
3348 1 -> (1.1)Mainline Build
3349 2->(1.04) Stability Build
3350 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003351 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003352 ((versionReported.minor>=1) && (versionReported.version>=1)))
3353 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3354 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003355
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003356 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003357 {
3358#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3359 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3360 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3361#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003362 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003363 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003364
3365 } while (0);
3366
3367}
3368
3369/**---------------------------------------------------------------------------
3370
Jeff Johnson295189b2012-06-20 16:38:30 -07003371 \brief hdd_wlan_startup() - HDD init function
3372
3373 This is the driver startup code executed once a WLAN device has been detected
3374
3375 \param - dev - Pointer to the underlying device
3376
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003377 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003378
3379 --------------------------------------------------------------------------*/
3380
3381int hdd_wlan_startup(struct device *dev )
3382{
3383 VOS_STATUS status;
3384 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003385 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003386 hdd_context_t *pHddCtx = NULL;
3387 v_CONTEXT_t pVosContext= NULL;
3388#ifdef WLAN_BTAMP_FEATURE
3389 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3390 WLANBAP_ConfigType btAmpConfig;
3391 hdd_config_t *pConfig;
3392#endif
3393 int ret;
3394#ifdef CONFIG_CFG80211
3395 struct wiphy *wiphy;
3396#endif
3397#ifdef ANI_BUS_TYPE_SDIO
3398 struct sdio_func *sdio_func_dev = dev_to_sdio_func(dev);
3399#endif //ANI_BUS_TYPE_SDIO
3400
3401 ENTER();
3402#ifdef CONFIG_CFG80211
3403 /*
3404 * cfg80211: wiphy allocation
3405 */
3406 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3407
3408 if(wiphy == NULL)
3409 {
3410 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003411 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003412 }
3413
3414 pHddCtx = wiphy_priv(wiphy);
3415
3416#else
3417
3418 pHddCtx = vos_mem_malloc ( sizeof( hdd_context_t ) );
3419 if(pHddCtx == NULL)
3420 {
3421 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003422 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07003423 }
3424
3425#endif
3426 //Initialize the adapter context to zeros.
3427 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3428
3429#ifdef CONFIG_CFG80211
3430 pHddCtx->wiphy = wiphy;
3431#endif
3432 hdd_prevent_suspend();
3433 pHddCtx->isLoadUnloadInProgress = TRUE;
3434
3435 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3436
3437 /*Get vos context here bcoz vos_open requires it*/
3438 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3439
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003440 if(pVosContext == NULL)
3441 {
3442 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3443 goto err_free_hdd_context;
3444 }
3445
Jeff Johnson295189b2012-06-20 16:38:30 -07003446 //Save the Global VOSS context in adapter context for future.
3447 pHddCtx->pvosContext = pVosContext;
3448
3449 //Save the adapter context in global context for future.
3450 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3451
3452#ifdef ANI_BUS_TYPE_SDIO
3453 // Set the private data for the device to our adapter.
3454 libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
3455 atomic_set(&pHddCtx->sdio_claim_count, 0);
3456#endif // ANI_BUS_TYPE_SDIO
3457
3458 pHddCtx->parent_dev = dev;
3459
3460 init_completion(&pHddCtx->full_pwr_comp_var);
3461 init_completion(&pHddCtx->standby_comp_var);
3462 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003463 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003464 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003465
3466 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3467
3468 // Load all config first as TL config is needed during vos_open
3469 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3470 if(pHddCtx->cfg_ini == NULL)
3471 {
3472 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3473 goto err_free_hdd_context;
3474 }
3475
3476 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3477
3478 // Read and parse the qcom_cfg.ini file
3479 status = hdd_parse_config_ini( pHddCtx );
3480 if ( VOS_STATUS_SUCCESS != status )
3481 {
3482 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3483 __func__, WLAN_INI_FILE);
3484 goto err_config;
3485 }
3486
3487#ifdef CONFIG_CFG80211
3488 /*
3489 * cfg80211: Initialization and registration ...
3490 */
3491 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3492 {
3493 hddLog(VOS_TRACE_LEVEL_FATAL,
3494 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3495 goto err_wiphy_reg;
3496 }
3497#endif
3498
3499#ifdef FEATURE_WLAN_INTEGRATED_SOC
3500 // Update WDI trace levels based upon the cfg.ini
3501 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3502 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3503 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3504 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3505 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3506 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3507 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3508 pHddCtx->cfg_ini->wdiTraceEnablePAL);
3509#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3510
3511#ifdef ANI_MANF_DIAG
3512 if(VOS_FTM_MODE == hdd_get_conparam())
3513 {
3514 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3515 {
3516 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3517 goto err_free_hdd_context;
3518 }
3519 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3520 return VOS_STATUS_SUCCESS;
3521 }
3522#endif
3523
3524 //Open watchdog module
3525 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3526 {
3527 status = vos_watchdog_open(pVosContext,
3528 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
3529
3530 if(!VOS_IS_STATUS_SUCCESS( status ))
3531 {
3532 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
3533#ifdef CONFIG_CFG80211
3534 goto err_wiphy_reg;
3535#else
3536 goto err_config;
3537#endif
3538 }
3539 }
3540
3541 pHddCtx->isLogpInProgress = FALSE;
3542 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3543
3544#ifdef ANI_BUS_TYPE_SDIO
3545 status = WLANBAL_Open(pHddCtx->pvosContext);
3546 if(!VOS_IS_STATUS_SUCCESS(status))
3547 {
3548 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3549 "%s: Failed to open BAL",__func__);
3550 goto err_wdclose;
3551 }
3552#endif // ANI_BUS_TYPE_SDIO
3553
3554 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
3555 if(!VOS_IS_STATUS_SUCCESS(status))
3556 {
3557 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
3558#ifdef ANI_BUS_TYPE_SDIO
3559 goto err_balclose;
3560#else
3561 goto err_wdclose;
3562#endif
3563 }
3564
3565
3566#ifdef ANI_BUS_TYPE_SDIO
3567 status = WLANSAL_Start(pHddCtx->pvosContext);
3568 if (!VOS_IS_STATUS_SUCCESS(status))
3569 {
3570 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
3571 goto err_clkvote;
3572 }
3573
3574 /* Start BAL */
3575 status = WLANBAL_Start(pHddCtx->pvosContext);
3576
3577 if (!VOS_IS_STATUS_SUCCESS(status))
3578 {
3579 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3580 "%s: Failed to start BAL",__func__);
3581 goto err_salstop;
3582 }
3583#endif // ANI_BUS_TYPE_SDIO
3584
3585#ifdef MSM_PLATFORM_7x30
3586 /* FIXME: Volans 2.0 configuration. Reconfigure 1.3v SW supply to 1.3v. It will be configured to
3587 * 1.4v in vos_ChipPowerup() routine above
3588 */
3589#endif
3590
3591 status = vos_open( &pVosContext, 0);
3592 if ( !VOS_IS_STATUS_SUCCESS( status ))
3593 {
3594 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
3595 goto err_balstop;
3596 }
3597
3598 /* Save the hal context in Adapter */
3599 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
3600
3601 if ( NULL == pHddCtx->hHal )
3602 {
3603 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
3604 goto err_vosclose;
3605 }
3606
Jeff Johnsone7245742012-09-05 17:12:55 -07003607#ifdef FEATURE_WLAN_INTEGRATED_SOC
3608 /* Vos preStart is calling */
3609 /* vos preStart which does cfg download should be called before set sme config which accesses/sets some cfgs */
3610 status = vos_preStart( pHddCtx->pvosContext );
3611 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3612 {
3613 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
3614 goto err_vosclose;
3615 }
3616#endif
3617
Jeff Johnson295189b2012-06-20 16:38:30 -07003618 // Set the SME configuration parameters...
3619 status = hdd_set_sme_config( pHddCtx );
3620
3621 if ( VOS_STATUS_SUCCESS != status )
3622 {
3623 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
3624 goto err_vosclose;
3625 }
3626
3627 //Initialize the WMM module
3628 status = hdd_wmm_init(pHddCtx);
3629 if (!VOS_IS_STATUS_SUCCESS(status))
3630 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003631 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003632 goto err_vosclose;
3633 }
3634
3635#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnson295189b2012-06-20 16:38:30 -07003636 /* In the integrated architecture we update the configuration from
3637 the INI file and from NV before vOSS has been started so that
3638 the final contents are available to send down to the cCPU */
3639
3640 // Apply the cfg.ini to cfg.dat
3641 if (FALSE == hdd_update_config_dat(pHddCtx))
3642 {
3643 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3644 goto err_vosclose;
3645 }
3646
3647 // Apply the NV to cfg.dat
3648 /* Prima Update MAC address only at here */
3649 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3650 {
3651#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
3652 /* There was not a valid set of MAC Addresses in NV. See if the
3653 default addresses were modified by the cfg.ini settings. If so,
3654 we'll use them, but if not, we'll autogenerate a set of MAC
3655 addresses based upon the device serial number */
3656
3657 static const v_MACADDR_t default_address =
3658 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
3659 unsigned int serialno;
3660 int i;
3661
3662 serialno = wcnss_get_serial_number();
3663 if ((0 != serialno) &&
3664 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
3665 sizeof(default_address))))
3666 {
3667 /* cfg.ini has the default address, invoke autogen logic */
3668
3669 /* MAC address has 3 bytes of OUI so we have a maximum of 3
3670 bytes of the serial number that can be used to generate
3671 the other 3 bytes of the MAC address. Mask off all but
3672 the lower 3 bytes (this will also make sure we don't
3673 overflow in the next step) */
3674 serialno &= 0x00FFFFFF;
3675
3676 /* we need a unique address for each session */
3677 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
3678
3679 /* autogen all addresses */
3680 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3681 {
3682 /* start with the entire default address */
3683 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
3684 /* then replace the lower 3 bytes */
3685 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
3686 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
3687 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
3688
3689 serialno++;
3690 }
3691
3692 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
3693 MAC_ADDRESS_STR,
3694 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
3695 }
3696 else
3697#endif //WLAN_AUTOGEN_MACADDR_FEATURE
3698 {
3699 hddLog(VOS_TRACE_LEVEL_ERROR,
3700 "%s: Invalid MAC address in NV, using MAC from ini file "
3701 MAC_ADDRESS_STR, __func__,
3702 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
3703 }
3704 }
3705 {
3706 eHalStatus halStatus;
3707 // Set the MAC Address
3708 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3709 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3710 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3711 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
3712
3713 if (!HAL_STATUS_SUCCESS( halStatus ))
3714 {
3715 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3716 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08003717 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07003718 }
3719 }
3720#endif // FEATURE_WLAN_INTEGRATED_SOC
3721
3722 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
3723 Note: Firmware image will be read and downloaded inside vos_start API */
3724 status = vos_start( pHddCtx->pvosContext );
3725 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3726 {
3727 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
3728 goto err_vosclose;
3729 }
3730
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003731 /* Exchange capability info between Host and FW and also get versioning info from FW */
3732 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003733
3734 status = hdd_post_voss_start_config( pHddCtx );
3735 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3736 {
3737 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
3738 __func__);
3739 goto err_vosstop;
3740 }
3741
3742#ifdef WLAN_SOFTAP_FEATURE
3743 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3744 {
3745 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
3746 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
3747 }
3748 else
3749 {
3750#endif
3751 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
3752 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
3753 if (pAdapter != NULL)
3754 {
3755#ifdef WLAN_FEATURE_P2P
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07003756 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
3757 if (p2p_dev_addr != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -07003758 {
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07003759 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
3760 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
3761
3762 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
3763 {
3764 /* Generate the P2P Device Address. This consists of the device's
3765 * primary MAC address with the locally administered bit set.
3766 */
3767 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
3768 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003769 }
3770 else
3771 {
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07003772 hddLog(VOS_TRACE_LEVEL_FATAL,
3773 "%s: Failed to allocate mac_address for p2p_device",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003774 __func__);
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07003775 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003776 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003777
3778 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
3779 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
3780 if ( NULL == pP2pAdapter )
3781 {
3782 hddLog(VOS_TRACE_LEVEL_FATAL,
3783 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003784 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07003785 goto err_close_adapter;
3786 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003787#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003788 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003789#ifdef WLAN_SOFTAP_FEATURE
3790 }
3791#endif
3792
3793 if( pAdapter == NULL )
3794 {
3795 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
3796#ifdef ANI_BUS_TYPE_SDIO
3797 goto err_balstop;
3798#else
3799 goto err_clkvote;
3800#endif
3801 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003802
Jeff Johnson295189b2012-06-20 16:38:30 -07003803#ifdef WLAN_BTAMP_FEATURE
3804 vStatus = WLANBAP_Open(pVosContext);
3805 if(!VOS_IS_STATUS_SUCCESS(vStatus))
3806 {
3807 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3808 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07003809 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003810 }
3811
3812 vStatus = BSL_Init(pVosContext);
3813 if(!VOS_IS_STATUS_SUCCESS(vStatus))
3814 {
3815 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3816 "%s: Failed to Init BSL",__func__);
3817 goto err_bap_close;
3818 }
3819 vStatus = WLANBAP_Start(pVosContext);
3820 if (!VOS_IS_STATUS_SUCCESS(vStatus))
3821 {
3822 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3823 "%s: Failed to start TL",__func__);
3824 goto err_bap_close;
3825 }
3826
3827 pConfig = pHddCtx->cfg_ini;
3828 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
3829 status = WLANBAP_SetConfig(&btAmpConfig);
3830
3831#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07003832
Jeff Johnson295189b2012-06-20 16:38:30 -07003833#ifdef FEATURE_WLAN_SCAN_PNO
3834 /*SME must send channel update configuration to RIVA*/
3835 sme_UpdateChannelConfig(pHddCtx->hHal);
3836#endif
3837
3838#ifdef FEATURE_WLAN_INTEGRATED_SOC
3839 /* Register with platform driver as client for Suspend/Resume */
3840 status = hddRegisterPmOps(pHddCtx);
3841 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3842 {
3843 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
3844#ifdef WLAN_BTAMP_FEATURE
3845 goto err_bap_stop;
3846#else
Jeff Johnsone7245742012-09-05 17:12:55 -07003847 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003848#endif //WLAN_BTAMP_FEATURE
3849 }
3850
3851 /* Register TM level change handler function to the platform */
3852 status = hddDevTmRegisterNotifyCallback(pHddCtx);
3853 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3854 {
3855 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
3856 goto err_unregister_pmops;
3857 }
3858#endif
3859
3860 /* register for riva power on lock to platform driver */
3861 if (req_riva_power_on_lock("wlan"))
3862 {
3863 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
3864 __func__);
3865 goto err_unregister_pmops;
3866 }
3867
3868#ifdef CONFIG_HAS_EARLYSUSPEND
3869 // Register suspend/resume callbacks
3870 if(pHddCtx->cfg_ini->nEnableSuspend)
3871 {
3872 register_wlan_suspend();
3873 }
3874#endif
3875
3876 // register net device notifier for device change notification
3877 ret = register_netdevice_notifier(&hdd_netdev_notifier);
3878
3879 if(ret < 0)
3880 {
3881 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
3882 goto err_free_power_on_lock;
3883 }
3884
3885 //Initialize the nlink service
3886 if(nl_srv_init() != 0)
3887 {
3888 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
3889 goto err_reg_netdev;
3890 }
3891
3892 //Initialize the BTC service
3893 if(btc_activate_service(pHddCtx) != 0)
3894 {
3895 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
3896 goto err_nl_srv;
3897 }
3898
3899#ifdef PTT_SOCK_SVC_ENABLE
3900 //Initialize the PTT service
3901 if(ptt_sock_activate_svc(pHddCtx) != 0)
3902 {
3903 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
3904 goto err_nl_srv;
3905 }
3906#endif
3907
Jeff Johnson295189b2012-06-20 16:38:30 -07003908#ifdef CONFIG_HAS_EARLYSUSPEND
3909 hdd_register_mcast_bcast_filter(pHddCtx);
3910#endif
3911#ifdef CONFIG_CFG80211
3912#ifdef WLAN_SOFTAP_FEATURE
3913 if (VOS_STA_SAP_MODE != hdd_get_conparam())
3914#endif
3915 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07003916 /* Action frame registered in one adapter which will
3917 * applicable to all interfaces
3918 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07003919 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003920 }
3921#endif
3922
3923 mutex_init(&pHddCtx->sap_lock);
3924
3925 pHddCtx->isLoadUnloadInProgress = FALSE;
3926
Jeff Johnsone7245742012-09-05 17:12:55 -07003927#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3928 /* Initialize the wake lcok */
3929 wake_lock_init(&pHddCtx->rx_wake_lock,
3930 WAKE_LOCK_SUSPEND,
3931 "qcom_rx_wakelock");
3932#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003933 /* Initialize the wake lcok */
3934 wake_lock_init(&pHddCtx->sap_wake_lock,
3935 WAKE_LOCK_SUSPEND,
3936 "qcom_sap_wakelock");
Jeff Johnsone7245742012-09-05 17:12:55 -07003937
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003938 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
3939 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07003940
3941 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3942 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003943
3944 // Initialize the restart logic
3945 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05303946
3947#ifdef FEATURE_WLAN_TDLS
3948 wlan_hdd_tdls_init(pAdapter->dev);
3949#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003950
3951 goto success;
3952
3953err_nl_srv:
3954 nl_srv_exit();
3955
3956err_reg_netdev:
3957 unregister_netdevice_notifier(&hdd_netdev_notifier);
3958
3959err_free_power_on_lock:
3960 free_riva_power_on_lock("wlan");
3961
3962err_unregister_pmops:
3963 hddDevTmUnregisterNotifyCallback(pHddCtx);
3964 hddDeregisterPmOps(pHddCtx);
3965
3966#ifdef WLAN_BTAMP_FEATURE
3967err_bap_stop:
3968 WLANBAP_Stop(pVosContext);
3969#endif
3970
3971#ifdef WLAN_BTAMP_FEATURE
3972err_bap_close:
3973 WLANBAP_Close(pVosContext);
3974#endif
3975
Jeff Johnson295189b2012-06-20 16:38:30 -07003976err_close_adapter:
3977 hdd_close_all_adapters( pHddCtx );
3978
3979err_vosstop:
3980 vos_stop(pVosContext);
3981
3982err_vosclose:
3983 status = vos_sched_close( pVosContext );
3984 if (!VOS_IS_STATUS_SUCCESS(status)) {
3985 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3986 "%s: Failed to close VOSS Scheduler", __func__);
3987 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
3988 }
3989 vos_close(pVosContext );
3990
3991err_balstop:
3992#ifdef ANI_BUS_TYPE_SDIO
3993#ifndef ANI_MANF_DIAG
3994 wlan_hdd_enable_deepsleep(pHddCtx->pvosContext);
3995#endif
3996
3997 WLANBAL_Stop(pHddCtx->pvosContext);
3998 WLANBAL_SuspendChip(pHddCtx->pvosContext);
3999#endif
4000
4001#ifdef ANI_BUS_TYPE_SDIO
4002err_salstop:
4003 WLANSAL_Stop(pHddCtx->pvosContext);
4004
4005#endif
4006err_clkvote:
4007 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4008
4009#ifdef ANI_BUS_TYPE_SDIO
4010err_balclose:
4011 WLANBAL_Close(pHddCtx->pvosContext);
4012#endif // ANI_BUS_TYPE_SDIO
4013
4014err_wdclose:
4015 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4016 vos_watchdog_close(pVosContext);
4017
4018#ifdef CONFIG_CFG80211
4019err_wiphy_reg:
4020 wiphy_unregister(wiphy) ;
4021#endif
4022
4023err_config:
4024 kfree(pHddCtx->cfg_ini);
4025 pHddCtx->cfg_ini= NULL;
4026
4027err_free_hdd_context:
4028 hdd_allow_suspend();
4029#ifdef CONFIG_CFG80211
4030 wiphy_free(wiphy) ;
4031 //kfree(wdev) ;
4032#else
4033 vos_mem_free( pHddCtx );
4034#endif
4035 VOS_BUG(1);
4036
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004037 if (hdd_is_ssr_required())
4038 {
4039 /* WDI timeout had happened during load, so SSR is needed here */
4040 subsystem_restart("wcnss");
4041 msleep(5000);
4042 }
4043 hdd_set_ssr_required (VOS_FALSE);
4044
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004045 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004046
4047success:
4048 EXIT();
4049 return 0;
4050}
4051
4052/**---------------------------------------------------------------------------
4053
Jeff Johnson32d95a32012-09-10 13:15:23 -07004054 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004055
Jeff Johnson32d95a32012-09-10 13:15:23 -07004056 This is the driver entry point - called in different timeline depending
4057 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004058
4059 \param - None
4060
4061 \return - 0 for success, non zero for failure
4062
4063 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004064static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004065{
4066 VOS_STATUS status;
4067 v_CONTEXT_t pVosContext = NULL;
4068#ifdef ANI_BUS_TYPE_SDIO
4069 struct sdio_func *sdio_func_dev = NULL;
4070 unsigned int attempts = 0;
4071#endif // ANI_BUS_TYPE_SDIO
4072 struct device *dev = NULL;
4073 int ret_status = 0;
4074
4075 ENTER();
4076
Jeff Johnsone7245742012-09-05 17:12:55 -07004077#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07004078 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004079#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004080
4081 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4082 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4083
4084 //Power Up Libra WLAN card first if not already powered up
4085 status = vos_chipPowerUp(NULL,NULL,NULL);
4086 if (!VOS_IS_STATUS_SUCCESS(status))
4087 {
4088 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4089 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004090 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004091 }
4092
4093#ifdef ANI_BUS_TYPE_SDIO
4094 //SDIO Polling should be turned on for card detection. When using Android Wi-Fi GUI
4095 //users need not trigger SDIO polling explicitly. However when loading drivers via
4096 //command line (Adb shell), users must turn on SDIO polling prior to loading WLAN.
4097 do {
4098 sdio_func_dev = libra_getsdio_funcdev();
4099 if (NULL == sdio_func_dev) {
4100 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
4101 attempts++;
4102 }
4103 else {
4104 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
4105 dev = &sdio_func_dev->dev;
4106 break;
4107 }
4108
4109 if(attempts == 7)
4110 break;
4111
4112 msleep(250);
4113
4114 }while (attempts < 7);
4115
4116 //Retry to detect the card again by Powering Down the chip and Power up the chip
4117 //again. This retry is done to recover from CRC Error
4118 if (NULL == sdio_func_dev) {
4119
4120 attempts = 0;
4121
4122 //Vote off any PMIC voltage supplies
4123 vos_chipPowerDown(NULL, NULL, NULL);
4124
4125 msleep(1000);
4126
4127 //Power Up Libra WLAN card first if not already powered up
4128 status = vos_chipPowerUp(NULL,NULL,NULL);
4129 if (!VOS_IS_STATUS_SUCCESS(status))
4130 {
4131 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
4132 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004133 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004134 }
4135
4136 do {
4137 sdio_func_dev = libra_getsdio_funcdev();
4138 if (NULL == sdio_func_dev) {
4139 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
4140 attempts++;
4141 }
4142 else {
4143 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
4144 dev = &sdio_func_dev->dev;
4145 break;
4146 }
4147
4148 if(attempts == 2)
4149 break;
4150
4151 msleep(1000);
4152
4153 }while (attempts < 3);
4154 }
4155
4156#endif // ANI_BUS_TYPE_SDIO
4157
4158#ifdef ANI_BUS_TYPE_PCI
4159
4160 dev = wcnss_wlan_get_device();
4161
4162#endif // ANI_BUS_TYPE_PCI
4163
4164#ifdef ANI_BUS_TYPE_PLATFORM
4165 dev = wcnss_wlan_get_device();
4166#endif // ANI_BUS_TYPE_PLATFORM
4167
4168
4169 do {
4170 if (NULL == dev) {
4171 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4172 ret_status = -1;
4173 break;
4174 }
4175
4176#ifdef MEMORY_DEBUG
4177 vos_mem_init();
4178#endif
4179
4180#ifdef TIMER_MANAGER
4181 vos_timer_manager_init();
4182#endif
4183
4184 /* Preopen VOSS so that it is ready to start at least SAL */
4185 status = vos_preOpen(&pVosContext);
4186
4187 if (!VOS_IS_STATUS_SUCCESS(status))
4188 {
4189 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4190 ret_status = -1;
4191 break;
4192 }
4193
4194#ifdef ANI_BUS_TYPE_SDIO
4195 /* Now Open SAL */
4196 status = WLANSAL_Open(pVosContext, 0);
4197
4198 if(!VOS_IS_STATUS_SUCCESS(status))
4199 {
4200 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to open SAL", __func__);
4201
4202 /* If unable to open, cleanup and return failure */
4203 vos_preClose( &pVosContext );
4204 ret_status = -1;
4205 break;
4206 }
4207#endif // ANI_BUS_TYPE_SDIO
4208
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004209#ifndef MODULE
4210 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4211 */
4212 hdd_set_conparam((v_UINT_t)con_mode);
4213#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004214
4215 // Call our main init function
4216 if(hdd_wlan_startup(dev)) {
4217 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
4218 __func__);
4219#ifdef ANI_BUS_TYPE_SDIO
4220 WLANSAL_Close(pVosContext);
4221#endif // ANI_BUS_TYPE_SDIO
4222 vos_preClose( &pVosContext );
4223 ret_status = -1;
4224 break;
4225 }
4226
4227 /* Cancel the vote for XO Core ON
4228 * This is done here for safety purposes in case we re-initialize without turning
4229 * it OFF in any error scenario.
4230 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004231 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004232 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004233 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004234 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4235 {
4236 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4237 " Power consumed will be high\n");
4238 }
4239 } while (0);
4240
4241 if (0 != ret_status)
4242 {
4243 //Assert Deep sleep signal now to put Libra HW in lowest power state
4244 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4245 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4246
4247 //Vote off any PMIC voltage supplies
4248 vos_chipPowerDown(NULL, NULL, NULL);
4249#ifdef TIMER_MANAGER
4250 vos_timer_exit();
4251#endif
4252#ifdef MEMORY_DEBUG
4253 vos_mem_exit();
4254#endif
4255
Jeff Johnsone7245742012-09-05 17:12:55 -07004256#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07004257 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004258#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004259 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4260 }
4261 else
4262 {
4263 //Send WLAN UP indication to Nlink Service
4264 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4265
4266 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4267
4268 }
4269
4270 EXIT();
4271
4272 return ret_status;
4273}
4274
Jeff Johnson32d95a32012-09-10 13:15:23 -07004275/**---------------------------------------------------------------------------
4276
4277 \brief hdd_module_init() - Init Function
4278
4279 This is the driver entry point (invoked when module is loaded using insmod)
4280
4281 \param - None
4282
4283 \return - 0 for success, non zero for failure
4284
4285 --------------------------------------------------------------------------*/
4286#ifdef MODULE
4287static int __init hdd_module_init ( void)
4288{
4289 return hdd_driver_init();
4290}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004291#else /* #ifdef MODULE */
4292static int __init hdd_module_init ( void)
4293{
4294 /* Driver initialization is delayed to fwpath_changed_handler */
4295 return 0;
4296}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004297#endif /* #ifdef MODULE */
4298
Jeff Johnson295189b2012-06-20 16:38:30 -07004299
4300/**---------------------------------------------------------------------------
4301
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004302 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004303
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004304 This is the driver exit point (invoked when module is unloaded using rmmod
4305 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004306
4307 \param - None
4308
4309 \return - None
4310
4311 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004312static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004313{
4314 hdd_context_t *pHddCtx = NULL;
4315 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004316
4317 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4318
4319 //Get the global vos context
4320 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4321
4322 if(!pVosContext)
4323 {
4324 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4325 goto done;
4326 }
4327
4328 //Get the HDD context.
4329 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4330
4331 if(!pHddCtx)
4332 {
4333 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4334 }
4335 else
4336 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004337 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004338 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004339 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4340 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004341 }
4342
4343 pHddCtx->isLoadUnloadInProgress = TRUE;
4344 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4345
4346 //Do all the cleanup before deregistering the driver
4347 hdd_wlan_exit(pHddCtx);
4348 }
4349
4350#ifdef ANI_BUS_TYPE_SDIO
4351 WLANSAL_Close(pVosContext);
4352#endif // ANI_BUS_TYPE_SDIO
4353
4354 vos_preClose( &pVosContext );
4355
4356#ifdef TIMER_MANAGER
4357 vos_timer_exit();
4358#endif
4359#ifdef MEMORY_DEBUG
4360 vos_mem_exit();
4361#endif
4362
4363done:
Jeff Johnsone7245742012-09-05 17:12:55 -07004364#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07004365 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004366#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004367 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4368}
4369
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004370/**---------------------------------------------------------------------------
4371
4372 \brief hdd_module_exit() - Exit function
4373
4374 This is the driver exit point (invoked when module is unloaded using rmmod)
4375
4376 \param - None
4377
4378 \return - None
4379
4380 --------------------------------------------------------------------------*/
4381static void __exit hdd_module_exit(void)
4382{
4383 hdd_driver_exit();
4384}
4385
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004386#ifdef MODULE
4387static int fwpath_changed_handler(const char *kmessage,
4388 struct kernel_param *kp)
4389{
4390 /* nothing to do when driver is DLKM */
4391 return 0;
4392}
4393
4394static int con_mode_handler(const char *kmessage,
4395 struct kernel_param *kp)
4396{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004397 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004398}
4399#else /* #ifdef MODULE */
4400/**---------------------------------------------------------------------------
4401
4402 \brief fwpath_changed_handler() - Handler Function
4403
4404 This is the driver entry point
4405 - delayed driver initialization when driver is statically linked
4406 - invoked when module parameter fwpath is modified from userpspace to signal
4407 initializing the WLAN driver
4408
4409 \return - 0 for success, non zero for failure
4410
4411 --------------------------------------------------------------------------*/
4412static int fwpath_changed_handler(const char *kmessage,
4413 struct kernel_param *kp)
4414{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004415 int ret_status;
4416
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004417 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004418 ret_status = hdd_driver_init();
4419 wlan_hdd_inited = ret_status ? 0 : 1;
4420 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004421 }
4422
4423 hdd_driver_exit();
4424
4425 msleep(200);
4426
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004427 ret_status = hdd_driver_init();
4428 wlan_hdd_inited = ret_status ? 0 : 1;
4429 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004430}
4431
Jeff Johnson295189b2012-06-20 16:38:30 -07004432/**---------------------------------------------------------------------------
4433
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004434 \brief con_mode_handler() -
4435
4436 Handler function for module param con_mode when it is changed by userspace
4437 Dynamically linked - do nothing
4438 Statically linked - exit and init driver, as in rmmod and insmod
4439
4440 \param -
4441
4442 \return -
4443
4444 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004445static int con_mode_handler(const char *kmessage,
4446 struct kernel_param *kp)
4447{
4448 int ret = param_set_int(kmessage, kp);
4449
4450 if (ret)
4451 return ret;
4452
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004453 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004454}
4455#endif /* #ifdef MODULE */
4456
4457/**---------------------------------------------------------------------------
4458
Jeff Johnson295189b2012-06-20 16:38:30 -07004459 \brief hdd_get_conparam() -
4460
4461 This is the driver exit point (invoked when module is unloaded using rmmod)
4462
4463 \param - None
4464
4465 \return - tVOS_CON_MODE
4466
4467 --------------------------------------------------------------------------*/
4468tVOS_CON_MODE hdd_get_conparam ( void )
4469{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004470#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004471 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004472#else
4473 return (tVOS_CON_MODE)curr_con_mode;
4474#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004475}
4476void hdd_set_conparam ( v_UINT_t newParam )
4477{
4478 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004479#ifndef MODULE
4480 curr_con_mode = con_mode;
4481#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004482}
4483/**---------------------------------------------------------------------------
4484
4485 \brief hdd_softap_sta_deauth() - function
4486
4487 This to take counter measure to handle deauth req from HDD
4488
4489 \param - pAdapter - Pointer to the HDD
4490
4491 \param - enable - boolean value
4492
4493 \return - None
4494
4495 --------------------------------------------------------------------------*/
4496
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004497VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004498{
Jeff Johnson295189b2012-06-20 16:38:30 -07004499 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004500 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004501#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
4502 tHalHandle hHalHandle;
4503#endif
4504
4505 ENTER();
4506
4507 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4508
4509 //Ignore request to deauth bcmc station
4510 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004511 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004512
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004513 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004514
4515 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004516 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004517}
4518
4519/**---------------------------------------------------------------------------
4520
4521 \brief hdd_softap_sta_disassoc() - function
4522
4523 This to take counter measure to handle deauth req from HDD
4524
4525 \param - pAdapter - Pointer to the HDD
4526
4527 \param - enable - boolean value
4528
4529 \return - None
4530
4531 --------------------------------------------------------------------------*/
4532
4533void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4534{
4535 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4536
4537 ENTER();
4538
4539 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4540
4541 //Ignore request to disassoc bcmc station
4542 if( pDestMacAddress[0] & 0x1 )
4543 return;
4544
4545 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4546}
4547
4548void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4549{
4550 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4551
4552 ENTER();
4553
4554 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4555
4556 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4557}
4558
Jeff Johnson295189b2012-06-20 16:38:30 -07004559/**---------------------------------------------------------------------------
4560 *
4561 * \brief hdd_get__concurrency_mode() -
4562 *
4563 *
4564 * \param - None
4565 *
4566 * \return - CONCURRENCY MODE
4567 *
4568 * --------------------------------------------------------------------------*/
4569tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4570{
4571 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4572 hdd_context_t *pHddCtx;
4573
4574 if (NULL != pVosContext)
4575 {
4576 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4577 if (NULL != pHddCtx)
4578 {
4579 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4580 }
4581 }
4582
4583 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004584 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004585 return VOS_STA;
4586}
4587
4588/* Decide whether to allow/not the apps power collapse.
4589 * Allow apps power collapse if we are in connected state.
4590 * if not, allow only if we are in IMPS */
4591v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4592{
4593 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4594 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4595 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4596 hdd_adapter_t *pAdapter = NULL;
4597 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004598 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004599
4600#ifdef WLAN_SOFTAP_FEATURE
4601 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4602 return TRUE;
4603#endif
4604
Yathish9f22e662012-12-10 14:21:35 -08004605 concurrent_state = hdd_get_concurrency_mode();
4606
4607#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4608 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4609 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4610 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4611 return TRUE;
4612#endif
4613
Jeff Johnson295189b2012-06-20 16:38:30 -07004614 /*loop through all adapters. TBD fix for Concurrency */
4615 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4616 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4617 {
4618 pAdapter = pAdapterNode->pAdapter;
4619 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4620 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4621 {
4622 if ((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
4623 && (pmcState != IMPS && pmcState != BMPS
4624 && pmcState != STOPPED && pmcState != STANDBY))
4625 {
4626 return FALSE;
4627 }
4628 }
4629 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4630 pAdapterNode = pNext;
4631 }
4632 return TRUE;
4633}
4634
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08004635/* Decides whether to send suspend notification to Riva
4636 * if any adapter is in BMPS; then it is required */
4637v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
4638{
4639 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4640 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4641
4642 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
4643 {
4644 return TRUE;
4645 }
4646 return FALSE;
4647}
4648
Jeff Johnson295189b2012-06-20 16:38:30 -07004649void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4650{
4651 switch(mode)
4652 {
4653 case WLAN_HDD_INFRA_STATION:
4654#ifdef WLAN_FEATURE_P2P
4655 case WLAN_HDD_P2P_CLIENT:
4656 case WLAN_HDD_P2P_GO:
4657#endif
4658 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07004659 pHddCtx->concurrency_mode |= (1 << mode);
4660 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07004661 break;
4662 default:
4663 break;
4664
4665 }
4666 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4667 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4668}
4669
4670
4671void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4672{
4673 switch(mode)
4674 {
4675 case WLAN_HDD_INFRA_STATION:
4676#ifdef WLAN_FEATURE_P2P
4677 case WLAN_HDD_P2P_CLIENT:
4678 case WLAN_HDD_P2P_GO:
4679#endif
4680 case WLAN_HDD_SOFTAP:
4681 pHddCtx->no_of_sessions[mode]--;
4682 if (!(pHddCtx->no_of_sessions[mode]))
4683 pHddCtx->concurrency_mode &= (~(1 << mode));
4684 break;
4685 default:
4686 break;
4687 }
4688 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4689 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4690}
4691
Jeff Johnsone7245742012-09-05 17:12:55 -07004692/**---------------------------------------------------------------------------
4693 *
4694 * \brief wlan_hdd_restart_init
4695 *
4696 * This function initalizes restart timer/flag. An internal function.
4697 *
4698 * \param - pHddCtx
4699 *
4700 * \return - None
4701 *
4702 * --------------------------------------------------------------------------*/
4703
4704static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
4705{
4706 /* Initialize */
4707 pHddCtx->hdd_restart_retries = 0;
4708 atomic_set(&pHddCtx->isRestartInProgress, 0);
4709 vos_timer_init(&pHddCtx->hdd_restart_timer,
4710 VOS_TIMER_TYPE_SW,
4711 wlan_hdd_restart_timer_cb,
4712 pHddCtx);
4713}
4714/**---------------------------------------------------------------------------
4715 *
4716 * \brief wlan_hdd_restart_deinit
4717 *
4718 * This function cleans up the resources used. An internal function.
4719 *
4720 * \param - pHddCtx
4721 *
4722 * \return - None
4723 *
4724 * --------------------------------------------------------------------------*/
4725
4726static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
4727{
4728
4729 VOS_STATUS vos_status;
4730 /* Block any further calls */
4731 atomic_set(&pHddCtx->isRestartInProgress, 1);
4732 /* Cleanup */
4733 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
4734 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004735 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004736 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
4737 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004738 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004739
4740}
4741
4742/**---------------------------------------------------------------------------
4743 *
4744 * \brief wlan_hdd_framework_restart
4745 *
4746 * This function uses a cfg80211 API to start a framework initiated WLAN
4747 * driver module unload/load.
4748 *
4749 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
4750 *
4751 *
4752 * \param - pHddCtx
4753 *
4754 * \return - VOS_STATUS_SUCCESS: Success
4755 * VOS_STATUS_E_EMPTY: Adapter is Empty
4756 * VOS_STATUS_E_NOMEM: No memory
4757
4758 * --------------------------------------------------------------------------*/
4759
4760static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
4761{
4762 VOS_STATUS status = VOS_STATUS_SUCCESS;
4763 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4764 int len = (sizeof (struct ieee80211_mgmt));
4765 struct ieee80211_mgmt *mgmt = NULL;
4766
4767 /* Prepare the DEAUTH managment frame with reason code */
4768 mgmt = kzalloc(len, GFP_KERNEL);
4769 if(mgmt == NULL)
4770 {
4771 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08004772 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07004773 return VOS_STATUS_E_NOMEM;
4774 }
4775 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
4776
4777 /* Iterate over all adapters/devices */
4778 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4779 do
4780 {
4781 if( (status == VOS_STATUS_SUCCESS) &&
4782 pAdapterNode &&
4783 pAdapterNode->pAdapter)
4784 {
4785 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4786 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
4787 pAdapterNode->pAdapter->dev->name,
4788 pAdapterNode->pAdapter->device_mode,
4789 pHddCtx->hdd_restart_retries + 1);
4790 /*
4791 * CFG80211 event to restart the driver
4792 *
4793 * 'cfg80211_send_unprot_deauth' sends a
4794 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
4795 * of SME(Linux Kernel) state machine.
4796 *
4797 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
4798 * the driver.
4799 *
4800 */
4801
4802 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
4803 }
4804 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4805 pAdapterNode = pNext;
4806 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
4807
4808
4809 /* Free the allocated management frame */
4810 kfree(mgmt);
4811
4812 /* Retry until we unload or reach max count */
4813 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
4814 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
4815
4816 return status;
4817
4818}
4819/**---------------------------------------------------------------------------
4820 *
4821 * \brief wlan_hdd_restart_timer_cb
4822 *
4823 * Restart timer callback. An internal function.
4824 *
4825 * \param - User data:
4826 *
4827 * \return - None
4828 *
4829 * --------------------------------------------------------------------------*/
4830
4831void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
4832{
4833 hdd_context_t *pHddCtx = usrDataForCallback;
4834 wlan_hdd_framework_restart(pHddCtx);
4835 return;
4836
4837}
4838
4839
4840/**---------------------------------------------------------------------------
4841 *
4842 * \brief wlan_hdd_restart_driver
4843 *
4844 * This function sends an event to supplicant to restart the WLAN driver.
4845 *
4846 * This function is called from vos_wlanRestart.
4847 *
4848 * \param - pHddCtx
4849 *
4850 * \return - VOS_STATUS_SUCCESS: Success
4851 * VOS_STATUS_E_EMPTY: Adapter is Empty
4852 * VOS_STATUS_E_ALREADY: Request already in progress
4853
4854 * --------------------------------------------------------------------------*/
4855VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
4856{
4857 VOS_STATUS status = VOS_STATUS_SUCCESS;
4858
4859 /* A tight check to make sure reentrancy */
4860 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
4861 {
4862 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
4863 "%s: WLAN restart is already in progress", __func__);
4864
4865 return VOS_STATUS_E_ALREADY;
4866 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004867 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07004868 * the reset interrupt. If it is DLKM, then use restart API
4869 */
4870#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07004871 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07004872#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08004873#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07004874 wcnss_reset_intr();
4875#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08004876#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004877
Jeff Johnsone7245742012-09-05 17:12:55 -07004878 return status;
4879}
4880
4881
Jeff Johnson295189b2012-06-20 16:38:30 -07004882//Register the module init/exit functions
4883module_init(hdd_module_init);
4884module_exit(hdd_module_exit);
4885
4886MODULE_LICENSE("Dual BSD/GPL");
4887MODULE_AUTHOR("Qualcomm Atheros, Inc.");
4888MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
4889
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004890module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
4891 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07004892
4893module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
4894 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);