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