blob: 7467c77a22f88c08a024a7a378c12e611c2effaf [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
Ng Chilam1322ea32012-12-27 17:33:08 -08002707#ifdef ANI_MANF_DIAG
2708 if (VOS_FTM_MODE != hdd_get_conparam())
2709#endif /* ANI_MANF_DIAG */
2710 {
2711 // Unloading, restart logic is no more required.
2712 wlan_hdd_restart_deinit(pHddCtx);
2713 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002714
Jeff Johnson295189b2012-06-20 16:38:30 -07002715#ifdef CONFIG_CFG80211
2716#ifdef WLAN_SOFTAP_FEATURE
2717 if (VOS_STA_SAP_MODE != hdd_get_conparam())
2718#endif
2719 {
2720#ifdef ANI_MANF_DIAG
2721 if (VOS_FTM_MODE != hdd_get_conparam())
2722#endif /* ANI_MANF_DIAG */
2723 {
2724 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
2725 WLAN_HDD_INFRA_STATION);
2726 if (pAdapter == NULL)
2727 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2728
2729 if (pAdapter != NULL)
2730 {
2731 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
2732 hdd_UnregisterWext(pAdapter->dev);
2733 }
2734 }
2735 }
2736#endif
2737
2738#ifdef ANI_MANF_DIAG
2739 if (VOS_FTM_MODE == hdd_get_conparam())
2740 {
2741 wlan_hdd_ftm_close(pHddCtx);
2742 goto free_hdd_ctx;
2743 }
2744#endif
2745 //Stop the Interface TX queue.
2746 //netif_tx_disable(pWlanDev);
2747 //netif_carrier_off(pWlanDev);
2748
2749#ifdef CONFIG_HAS_EARLYSUSPEND
2750 // unregister suspend/resume callbacks
2751 if(pHddCtx->cfg_ini->nEnableSuspend)
2752 {
2753 unregister_wlan_suspend();
2754 }
2755#endif
2756
2757#ifdef FEATURE_WLAN_INTEGRATED_SOC
2758#ifdef WLAN_SOFTAP_FEATURE
2759 if (VOS_STA_SAP_MODE == hdd_get_conparam())
2760 {
2761 pAdapter = hdd_get_adapter(pHddCtx,
2762 WLAN_HDD_SOFTAP);
2763 }
2764 else
2765 {
2766#endif
2767#ifdef ANI_MANF_DIAG
2768 if (VOS_FTM_MODE != hdd_get_conparam())
2769#endif /* ANI_MANF_DIAG */
2770 {
2771 pAdapter = hdd_get_adapter(pHddCtx,
2772 WLAN_HDD_INFRA_STATION);
2773 }
2774#ifdef WLAN_SOFTAP_FEATURE
2775 }
2776#endif
2777 /* DeRegister with platform driver as client for Suspend/Resume */
2778 vosStatus = hddDeregisterPmOps(pHddCtx);
2779 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2780 {
2781 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
2782 VOS_ASSERT(0);
2783 }
2784
2785 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
2786 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2787 {
2788 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
2789 }
2790#endif //FEATURE_WLAN_INTEGRATED_SOC
2791
2792 // Cancel any outstanding scan requests. We are about to close all
2793 // of our adapters, but an adapter structure is what SME passes back
2794 // to our callback function. Hence if there are any outstanding scan
2795 // requests then there is a race condition between when the adapter
2796 // is closed and when the callback is invoked. We try to resolve that
2797 // race condition here by canceling any outstanding scans before we
2798 // close the adapters.
2799 // Note that the scans may be cancelled in an asynchronous manner, so
2800 // ideally there needs to be some kind of synchronization. Rather than
2801 // introduce a new synchronization here, we will utilize the fact that
2802 // we are about to Request Full Power, and since that is synchronized,
2803 // the expectation is that by the time Request Full Power has completed,
2804 // all scans will be cancelled.
2805 hdd_abort_mac_scan( pHddCtx );
2806
2807 //Disable IMPS/BMPS as we do not want the device to enter any power
2808 //save mode during shutdown
2809 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2810 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2811 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
2812
2813 //Ensure that device is in full power as we will touch H/W during vos_Stop
2814 init_completion(&powerContext.completion);
2815 powerContext.magic = POWER_CONTEXT_MAGIC;
2816
2817 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
2818 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
2819
2820 if (eHAL_STATUS_SUCCESS != halStatus)
2821 {
2822 if (eHAL_STATUS_PMC_PENDING == halStatus)
2823 {
2824 /* request was sent -- wait for the response */
2825 lrc = wait_for_completion_interruptible_timeout(
2826 &powerContext.completion,
2827 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
2828 /* either we have a response or we timed out
2829 either way, first invalidate our magic */
2830 powerContext.magic = 0;
2831 if (lrc <= 0)
2832 {
2833 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002834 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07002835 /* there is a race condition such that the callback
2836 function could be executing at the same time we are. of
2837 primary concern is if the callback function had already
2838 verified the "magic" but hasn't yet set the completion
2839 variable. Since the completion variable is on our
2840 stack, we'll delay just a bit to make sure the data is
2841 still valid if that is the case */
2842 msleep(50);
2843 }
2844 }
2845 else
2846 {
2847 hddLog(VOS_TRACE_LEVEL_ERROR,
2848 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002849 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07002850 VOS_ASSERT(0);
2851 /* continue -- need to clean up as much as possible */
2852 }
2853 }
2854
2855 // Unregister the Net Device Notifier
2856 unregister_netdevice_notifier(&hdd_netdev_notifier);
2857
Jeff Johnson295189b2012-06-20 16:38:30 -07002858 hdd_stop_all_adapters( pHddCtx );
2859
2860#ifdef ANI_BUS_TYPE_SDIO
2861 sdio_func_dev = libra_getsdio_funcdev();
2862
2863 if(sdio_func_dev == NULL)
2864 {
2865 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
2866 VOS_ASSERT(0);
2867 return;
2868 }
2869
2870 sd_claim_host(sdio_func_dev);
2871
2872 /* Disable SDIO IRQ since we are exiting */
2873 libra_enable_sdio_irq(sdio_func_dev, 0);
2874
2875 sd_release_host(sdio_func_dev);
2876#endif // ANI_BUS_TYPE_SDIO
2877
2878#ifdef WLAN_BTAMP_FEATURE
2879 vosStatus = WLANBAP_Stop(pVosContext);
2880 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2881 {
2882 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2883 "%s: Failed to stop BAP",__func__);
2884 }
2885#endif //WLAN_BTAMP_FEATURE
2886
2887 //Stop all the modules
2888 vosStatus = vos_stop( pVosContext );
2889 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2890 {
2891 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2892 "%s: Failed to stop VOSS",__func__);
2893 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2894 }
2895
2896#ifdef ANI_BUS_TYPE_SDIO
2897 vosStatus = WLANBAL_Stop( pVosContext );
2898
2899 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN BAL STOP\n");
2900 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2901 {
2902 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2903 "%s: Failed to stop BAL",__func__);
2904 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2905 }
2906
2907 msleep(50);
2908 //Put the chip is standby before asserting deep sleep
2909 vosStatus = WLANBAL_SuspendChip( pVosContext );
2910
2911 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN Suspend Chip\n");
2912
2913 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2914 {
2915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2916 "%s: Failed to suspend chip ",__func__);
2917 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2918 }
2919 //Invoke SAL stop
2920 vosStatus = WLANSAL_Stop( pVosContext );
2921 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2922 {
2923 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2924 "%s: Failed to stop SAL",__func__);
2925 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2926 }
2927
2928#endif // ANI_BUS_TYPE_SDIO
2929
2930 //Assert Deep sleep signal now to put Libra HW in lowest power state
2931 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
2932 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2933
2934 //Vote off any PMIC voltage supplies
2935 vos_chipPowerDown(NULL, NULL, NULL);
2936
2937 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
2938
2939 //Clean up HDD Nlink Service
2940 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2941 nl_srv_exit();
2942
2943 //This requires pMac access, Call this before vos_close().
2944#ifdef CONFIG_HAS_EARLYSUSPEND
2945 hdd_unregister_mcast_bcast_filter(pHddCtx);
2946#endif
2947
2948 //Close the scheduler before calling vos_close to make sure no thread is
2949 // scheduled after the each module close is called i.e after all the data
2950 // structures are freed.
2951 vosStatus = vos_sched_close( pVosContext );
2952 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
2953 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2954 "%s: Failed to close VOSS Scheduler",__func__);
2955 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2956 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002957
2958#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
2959 /* Destroy the wake lock */
2960 wake_lock_destroy(&pHddCtx->rx_wake_lock);
2961#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08002962 /* Destroy the wake lock */
2963 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07002964
2965 //Close VOSS
2966 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
2967 vos_close(pVosContext);
2968
2969#ifdef ANI_BUS_TYPE_SDIO
2970 vosStatus = WLANBAL_Close(pVosContext);
2971 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2972 {
2973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2974 "%s: Failed to close BAL",__func__);
2975 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2976 }
2977 hddLog(VOS_TRACE_LEVEL_ERROR,"Returned WLAN BAL CLOSE\n\n\n\n");
2978#endif // ANI_BUS_TYPE_SDIO
2979
2980 //Close Watchdog
2981 if(pHddCtx->cfg_ini->fIsLogpEnabled)
2982 vos_watchdog_close(pVosContext);
2983
2984 /* Cancel the vote for XO Core ON.
2985 * This is done here to ensure there is no race condition since MC, TX and WD threads have
2986 * exited at this point
2987 */
2988 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
2989 " when WLAN is turned OFF\n");
2990 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
2991 {
2992 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
2993 " Not returning failure."
2994 " Power consumed will be high\n");
2995 }
2996
2997 hdd_close_all_adapters( pHddCtx );
2998
2999
3000 //Free up dynamically allocated members inside HDD Adapter
3001 kfree(pHddCtx->cfg_ini);
3002 pHddCtx->cfg_ini= NULL;
3003
3004 /* free the power on lock from platform driver */
3005 if (free_riva_power_on_lock("wlan"))
3006 {
3007 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3008 __func__);
3009 }
3010
3011#ifdef ANI_MANF_DIAG
3012free_hdd_ctx:
3013#endif
3014#ifdef CONFIG_CFG80211
3015 wiphy_unregister(wiphy) ;
3016 wiphy_free(wiphy) ;
3017#else
3018 vos_mem_free( pHddCtx );
3019#endif
3020 if (hdd_is_ssr_required())
3021 {
3022 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003023 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003024 msleep(5000);
3025 }
3026 hdd_set_ssr_required (VOS_FALSE);
3027}
3028
3029
3030/**---------------------------------------------------------------------------
3031
3032 \brief hdd_update_config_from_nv() - Function to update the contents of
3033 the running configuration with parameters taken from NV storage
3034
3035 \param - pHddCtx - Pointer to the HDD global context
3036
3037 \return - VOS_STATUS_SUCCESS if successful
3038
3039 --------------------------------------------------------------------------*/
3040static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3041{
3042#ifndef FEATURE_WLAN_INTEGRATED_SOC
3043 eHalStatus halStatus;
3044#endif
3045
3046#ifdef FEATURE_WLAN_INTEGRATED_SOC
3047 v_BOOL_t itemIsValid = VOS_FALSE;
3048 VOS_STATUS status;
3049 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3050 v_U8_t macLoop;
3051
3052 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3053 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3054 if(status != VOS_STATUS_SUCCESS)
3055 {
3056 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3057 return VOS_STATUS_E_FAILURE;
3058 }
3059
3060 if (itemIsValid == VOS_TRUE)
3061 {
3062 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3063 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3064 VOS_MAX_CONCURRENCY_PERSONA);
3065 if(status != VOS_STATUS_SUCCESS)
3066 {
3067 /* Get MAC from NV fail, not update CFG info
3068 * INI MAC value will be used for MAC setting */
3069 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3070 return VOS_STATUS_E_FAILURE;
3071 }
3072
3073 /* If first MAC is not valid, treat all others are not valid
3074 * Then all MACs will be got from ini file */
3075 if(vos_is_macaddr_zero(&macFromNV[0]))
3076 {
3077 /* MAC address in NV file is not configured yet */
3078 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3079 return VOS_STATUS_E_INVAL;
3080 }
3081
3082 /* Get MAC address from NV, update CFG info */
3083 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3084 {
3085 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3086 {
3087 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3088 /* This MAC is not valid, skip it
3089 * This MAC will be got from ini file */
3090 }
3091 else
3092 {
3093 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3094 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3095 VOS_MAC_ADDR_SIZE);
3096 }
3097 }
3098 }
3099 else
3100 {
3101 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3102 return VOS_STATUS_E_FAILURE;
3103 }
3104#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3105
3106#ifndef FEATURE_WLAN_INTEGRATED_SOC
3107#if 1 /* need to fix for concurrency */
3108 // Set the MAC Address
3109 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3110 halStatus = ccmCfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3111 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3112 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]),
3113 hdd_set_mac_addr_cb, VOS_FALSE );
3114
3115 if (!HAL_STATUS_SUCCESS( halStatus ))
3116 {
3117 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3118 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
3119 return VOS_STATUS_E_FAILURE;
3120 }
3121#endif
3122#endif
3123
3124 return VOS_STATUS_SUCCESS;
3125}
3126
3127/**---------------------------------------------------------------------------
3128
3129 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3130
3131 \param - pAdapter - Pointer to the HDD
3132
3133 \return - None
3134
3135 --------------------------------------------------------------------------*/
3136VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3137{
3138 eHalStatus halStatus;
3139 v_U32_t listenInterval;
3140
3141#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
3142 /* In the non-integrated architecture we update the configuration from
3143 the INI file and from NV after vOSS has been started
3144 */
3145
3146 // Apply the cfg.ini to cfg.dat
3147 if (FALSE == hdd_update_config_dat(pHddCtx))
3148 {
3149 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3150 return VOS_STATUS_E_FAILURE;
3151 }
3152
3153 // Apply the NV to cfg.dat
3154 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3155 {
3156 hddLog(VOS_TRACE_LEVEL_FATAL,
3157 "%s: config update from NV failed", __func__ );
3158 return VOS_STATUS_E_FAILURE;
3159 }
3160#endif // FEATURE_WLAN_NON_INTEGRATED_SOC
3161
3162 // Send ready indication to the HDD. This will kick off the MAC
3163 // into a 'running' state and should kick off an initial scan.
3164 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3165 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3166 {
3167 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3168 "code %08d [x%08x]",__func__, halStatus, halStatus );
3169 return VOS_STATUS_E_FAILURE;
3170 }
3171
3172 // Set default LI into HDD context,
3173 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3174 // And RIVA will crash
3175 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3176 pHddCtx->hdd_actual_LI_value = listenInterval;
3177
3178 return VOS_STATUS_SUCCESS;
3179}
3180
3181#ifdef ANI_BUS_TYPE_SDIO
3182
3183#ifndef ANI_MANF_DIAG
3184// Routine to initialize the PMU
3185void wlan_hdd_enable_deepsleep(v_VOID_t * pVosContext)
3186{
3187/*-------------- Need to fix this correctly while doing Deepsleep testing
3188 tANI_U32 regValue = 0;
3189
3190 regValue = QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_DEEP_SLEEP_EN_MASK |
3191 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_AON_MASK_MASK |
3192 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_SW_MASK_MASK |
3193 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_2P3_LPM_MASK_MASK;
3194
3195 WLANBAL_WriteRegister(pVosContext, QWLAN_PMU_LDO_CTRL_REG_REG, regValue);
3196---------------------*/
3197
3198 return;
3199}
3200#endif
3201#endif
3202
3203/* wake lock APIs for HDD */
3204void hdd_prevent_suspend(void)
3205{
Jeff Johnsone7245742012-09-05 17:12:55 -07003206#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07003207 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003208#else
3209 wcnss_prevent_suspend();
3210#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003211}
3212
3213void hdd_allow_suspend(void)
3214{
Jeff Johnsone7245742012-09-05 17:12:55 -07003215#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07003216 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003217#else
3218 wcnss_allow_suspend();
3219#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003220}
3221
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003222void hdd_allow_suspend_timeout(v_U32_t timeout)
3223{
3224#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
3225 wake_lock_timeout(&wlan_wake_lock, timeout);
3226#else
3227 /* Do nothing as there is no API in wcnss for timeout*/
3228#endif
3229}
3230
Jeff Johnson295189b2012-06-20 16:38:30 -07003231/**---------------------------------------------------------------------------
3232
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003233 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3234 information between Host and Riva
3235
3236 This function gets reported version of FW
3237 It also finds the version of Riva headers used to compile the host
3238 It compares the above two and prints a warning if they are different
3239 It gets the SW and HW version string
3240 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3241 indicating the features they support through a bitmap
3242
3243 \param - pHddCtx - Pointer to HDD context
3244
3245 \return - void
3246
3247 --------------------------------------------------------------------------*/
3248
3249void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3250{
3251
3252 tSirVersionType versionCompiled;
3253 tSirVersionType versionReported;
3254 tSirVersionString versionString;
3255 tANI_U8 fwFeatCapsMsgSupported = 0;
3256 VOS_STATUS vstatus;
3257
3258 /* retrieve and display WCNSS version information */
3259 do {
3260
3261 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3262 &versionCompiled);
3263 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3264 {
3265 hddLog(VOS_TRACE_LEVEL_FATAL,
3266 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003267 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003268 break;
3269 }
3270
3271 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3272 &versionReported);
3273 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3274 {
3275 hddLog(VOS_TRACE_LEVEL_FATAL,
3276 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003277 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003278 break;
3279 }
3280
3281 if ((versionCompiled.major != versionReported.major) ||
3282 (versionCompiled.minor != versionReported.minor) ||
3283 (versionCompiled.version != versionReported.version) ||
3284 (versionCompiled.revision != versionReported.revision))
3285 {
3286 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3287 "Host expected %u.%u.%u.%u\n",
3288 WLAN_MODULE_NAME,
3289 (int)versionReported.major,
3290 (int)versionReported.minor,
3291 (int)versionReported.version,
3292 (int)versionReported.revision,
3293 (int)versionCompiled.major,
3294 (int)versionCompiled.minor,
3295 (int)versionCompiled.version,
3296 (int)versionCompiled.revision);
3297 }
3298 else
3299 {
3300 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3301 WLAN_MODULE_NAME,
3302 (int)versionReported.major,
3303 (int)versionReported.minor,
3304 (int)versionReported.version,
3305 (int)versionReported.revision);
3306 }
3307
3308 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3309 versionString,
3310 sizeof(versionString));
3311 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3312 {
3313 hddLog(VOS_TRACE_LEVEL_FATAL,
3314 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003315 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003316 break;
3317 }
3318
3319 pr_info("%s: WCNSS software version %s\n",
3320 WLAN_MODULE_NAME, versionString);
3321
3322 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3323 versionString,
3324 sizeof(versionString));
3325 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3326 {
3327 hddLog(VOS_TRACE_LEVEL_FATAL,
3328 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003329 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003330 break;
3331 }
3332
3333 pr_info("%s: WCNSS hardware version %s\n",
3334 WLAN_MODULE_NAME, versionString);
3335
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003336 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3337 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003338 send the message only if it the riva is 1.1
3339 minor numbers for different riva branches:
3340 0 -> (1.0)Mainline Build
3341 1 -> (1.1)Mainline Build
3342 2->(1.04) Stability Build
3343 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003344 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003345 ((versionReported.minor>=1) && (versionReported.version>=1)))
3346 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3347 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003348
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003349 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003350 {
3351#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3352 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3353 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3354#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003355 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003356 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003357
3358 } while (0);
3359
3360}
3361
3362/**---------------------------------------------------------------------------
3363
Jeff Johnson295189b2012-06-20 16:38:30 -07003364 \brief hdd_wlan_startup() - HDD init function
3365
3366 This is the driver startup code executed once a WLAN device has been detected
3367
3368 \param - dev - Pointer to the underlying device
3369
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003370 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003371
3372 --------------------------------------------------------------------------*/
3373
3374int hdd_wlan_startup(struct device *dev )
3375{
3376 VOS_STATUS status;
3377 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003378 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003379 hdd_context_t *pHddCtx = NULL;
3380 v_CONTEXT_t pVosContext= NULL;
3381#ifdef WLAN_BTAMP_FEATURE
3382 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3383 WLANBAP_ConfigType btAmpConfig;
3384 hdd_config_t *pConfig;
3385#endif
3386 int ret;
3387#ifdef CONFIG_CFG80211
3388 struct wiphy *wiphy;
3389#endif
3390#ifdef ANI_BUS_TYPE_SDIO
3391 struct sdio_func *sdio_func_dev = dev_to_sdio_func(dev);
3392#endif //ANI_BUS_TYPE_SDIO
3393
3394 ENTER();
3395#ifdef CONFIG_CFG80211
3396 /*
3397 * cfg80211: wiphy allocation
3398 */
3399 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3400
3401 if(wiphy == NULL)
3402 {
3403 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003404 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003405 }
3406
3407 pHddCtx = wiphy_priv(wiphy);
3408
3409#else
3410
3411 pHddCtx = vos_mem_malloc ( sizeof( hdd_context_t ) );
3412 if(pHddCtx == NULL)
3413 {
3414 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003415 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07003416 }
3417
3418#endif
3419 //Initialize the adapter context to zeros.
3420 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3421
3422#ifdef CONFIG_CFG80211
3423 pHddCtx->wiphy = wiphy;
3424#endif
3425 hdd_prevent_suspend();
3426 pHddCtx->isLoadUnloadInProgress = TRUE;
3427
3428 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3429
3430 /*Get vos context here bcoz vos_open requires it*/
3431 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3432
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003433 if(pVosContext == NULL)
3434 {
3435 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3436 goto err_free_hdd_context;
3437 }
3438
Jeff Johnson295189b2012-06-20 16:38:30 -07003439 //Save the Global VOSS context in adapter context for future.
3440 pHddCtx->pvosContext = pVosContext;
3441
3442 //Save the adapter context in global context for future.
3443 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3444
3445#ifdef ANI_BUS_TYPE_SDIO
3446 // Set the private data for the device to our adapter.
3447 libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
3448 atomic_set(&pHddCtx->sdio_claim_count, 0);
3449#endif // ANI_BUS_TYPE_SDIO
3450
3451 pHddCtx->parent_dev = dev;
3452
3453 init_completion(&pHddCtx->full_pwr_comp_var);
3454 init_completion(&pHddCtx->standby_comp_var);
3455 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003456 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003457 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003458
3459 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3460
3461 // Load all config first as TL config is needed during vos_open
3462 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3463 if(pHddCtx->cfg_ini == NULL)
3464 {
3465 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3466 goto err_free_hdd_context;
3467 }
3468
3469 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3470
3471 // Read and parse the qcom_cfg.ini file
3472 status = hdd_parse_config_ini( pHddCtx );
3473 if ( VOS_STATUS_SUCCESS != status )
3474 {
3475 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3476 __func__, WLAN_INI_FILE);
3477 goto err_config;
3478 }
3479
3480#ifdef CONFIG_CFG80211
3481 /*
3482 * cfg80211: Initialization and registration ...
3483 */
3484 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3485 {
3486 hddLog(VOS_TRACE_LEVEL_FATAL,
3487 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3488 goto err_wiphy_reg;
3489 }
3490#endif
3491
3492#ifdef FEATURE_WLAN_INTEGRATED_SOC
3493 // Update WDI trace levels based upon the cfg.ini
3494 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3495 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3496 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3497 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3498 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3499 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3500 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3501 pHddCtx->cfg_ini->wdiTraceEnablePAL);
3502#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3503
3504#ifdef ANI_MANF_DIAG
3505 if(VOS_FTM_MODE == hdd_get_conparam())
3506 {
3507 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3508 {
3509 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3510 goto err_free_hdd_context;
3511 }
3512 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3513 return VOS_STATUS_SUCCESS;
3514 }
3515#endif
3516
3517 //Open watchdog module
3518 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3519 {
3520 status = vos_watchdog_open(pVosContext,
3521 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
3522
3523 if(!VOS_IS_STATUS_SUCCESS( status ))
3524 {
3525 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
3526#ifdef CONFIG_CFG80211
3527 goto err_wiphy_reg;
3528#else
3529 goto err_config;
3530#endif
3531 }
3532 }
3533
3534 pHddCtx->isLogpInProgress = FALSE;
3535 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3536
3537#ifdef ANI_BUS_TYPE_SDIO
3538 status = WLANBAL_Open(pHddCtx->pvosContext);
3539 if(!VOS_IS_STATUS_SUCCESS(status))
3540 {
3541 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3542 "%s: Failed to open BAL",__func__);
3543 goto err_wdclose;
3544 }
3545#endif // ANI_BUS_TYPE_SDIO
3546
3547 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
3548 if(!VOS_IS_STATUS_SUCCESS(status))
3549 {
3550 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
3551#ifdef ANI_BUS_TYPE_SDIO
3552 goto err_balclose;
3553#else
3554 goto err_wdclose;
3555#endif
3556 }
3557
3558
3559#ifdef ANI_BUS_TYPE_SDIO
3560 status = WLANSAL_Start(pHddCtx->pvosContext);
3561 if (!VOS_IS_STATUS_SUCCESS(status))
3562 {
3563 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
3564 goto err_clkvote;
3565 }
3566
3567 /* Start BAL */
3568 status = WLANBAL_Start(pHddCtx->pvosContext);
3569
3570 if (!VOS_IS_STATUS_SUCCESS(status))
3571 {
3572 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3573 "%s: Failed to start BAL",__func__);
3574 goto err_salstop;
3575 }
3576#endif // ANI_BUS_TYPE_SDIO
3577
3578#ifdef MSM_PLATFORM_7x30
3579 /* FIXME: Volans 2.0 configuration. Reconfigure 1.3v SW supply to 1.3v. It will be configured to
3580 * 1.4v in vos_ChipPowerup() routine above
3581 */
3582#endif
3583
3584 status = vos_open( &pVosContext, 0);
3585 if ( !VOS_IS_STATUS_SUCCESS( status ))
3586 {
3587 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
3588 goto err_balstop;
3589 }
3590
3591 /* Save the hal context in Adapter */
3592 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
3593
3594 if ( NULL == pHddCtx->hHal )
3595 {
3596 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
3597 goto err_vosclose;
3598 }
3599
Jeff Johnsone7245742012-09-05 17:12:55 -07003600#ifdef FEATURE_WLAN_INTEGRATED_SOC
3601 /* Vos preStart is calling */
3602 /* vos preStart which does cfg download should be called before set sme config which accesses/sets some cfgs */
3603 status = vos_preStart( pHddCtx->pvosContext );
3604 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3605 {
3606 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
3607 goto err_vosclose;
3608 }
3609#endif
3610
Jeff Johnson295189b2012-06-20 16:38:30 -07003611 // Set the SME configuration parameters...
3612 status = hdd_set_sme_config( pHddCtx );
3613
3614 if ( VOS_STATUS_SUCCESS != status )
3615 {
3616 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
3617 goto err_vosclose;
3618 }
3619
3620 //Initialize the WMM module
3621 status = hdd_wmm_init(pHddCtx);
3622 if (!VOS_IS_STATUS_SUCCESS(status))
3623 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003624 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003625 goto err_vosclose;
3626 }
3627
3628#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnson295189b2012-06-20 16:38:30 -07003629 /* In the integrated architecture we update the configuration from
3630 the INI file and from NV before vOSS has been started so that
3631 the final contents are available to send down to the cCPU */
3632
3633 // Apply the cfg.ini to cfg.dat
3634 if (FALSE == hdd_update_config_dat(pHddCtx))
3635 {
3636 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3637 goto err_vosclose;
3638 }
3639
3640 // Apply the NV to cfg.dat
3641 /* Prima Update MAC address only at here */
3642 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3643 {
3644#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
3645 /* There was not a valid set of MAC Addresses in NV. See if the
3646 default addresses were modified by the cfg.ini settings. If so,
3647 we'll use them, but if not, we'll autogenerate a set of MAC
3648 addresses based upon the device serial number */
3649
3650 static const v_MACADDR_t default_address =
3651 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
3652 unsigned int serialno;
3653 int i;
3654
3655 serialno = wcnss_get_serial_number();
3656 if ((0 != serialno) &&
3657 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
3658 sizeof(default_address))))
3659 {
3660 /* cfg.ini has the default address, invoke autogen logic */
3661
3662 /* MAC address has 3 bytes of OUI so we have a maximum of 3
3663 bytes of the serial number that can be used to generate
3664 the other 3 bytes of the MAC address. Mask off all but
3665 the lower 3 bytes (this will also make sure we don't
3666 overflow in the next step) */
3667 serialno &= 0x00FFFFFF;
3668
3669 /* we need a unique address for each session */
3670 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
3671
3672 /* autogen all addresses */
3673 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3674 {
3675 /* start with the entire default address */
3676 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
3677 /* then replace the lower 3 bytes */
3678 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
3679 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
3680 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
3681
3682 serialno++;
3683 }
3684
3685 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
3686 MAC_ADDRESS_STR,
3687 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
3688 }
3689 else
3690#endif //WLAN_AUTOGEN_MACADDR_FEATURE
3691 {
3692 hddLog(VOS_TRACE_LEVEL_ERROR,
3693 "%s: Invalid MAC address in NV, using MAC from ini file "
3694 MAC_ADDRESS_STR, __func__,
3695 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
3696 }
3697 }
3698 {
3699 eHalStatus halStatus;
3700 // Set the MAC Address
3701 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3702 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3703 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3704 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
3705
3706 if (!HAL_STATUS_SUCCESS( halStatus ))
3707 {
3708 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3709 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08003710 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07003711 }
3712 }
3713#endif // FEATURE_WLAN_INTEGRATED_SOC
3714
3715 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
3716 Note: Firmware image will be read and downloaded inside vos_start API */
3717 status = vos_start( pHddCtx->pvosContext );
3718 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3719 {
3720 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
3721 goto err_vosclose;
3722 }
3723
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003724 /* Exchange capability info between Host and FW and also get versioning info from FW */
3725 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003726
3727 status = hdd_post_voss_start_config( pHddCtx );
3728 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3729 {
3730 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
3731 __func__);
3732 goto err_vosstop;
3733 }
3734
3735#ifdef WLAN_SOFTAP_FEATURE
3736 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3737 {
3738 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
3739 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
3740 }
3741 else
3742 {
3743#endif
3744 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
3745 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
3746 if (pAdapter != NULL)
3747 {
3748#ifdef WLAN_FEATURE_P2P
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07003749 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
3750 if (p2p_dev_addr != NULL)
Jeff Johnson295189b2012-06-20 16:38:30 -07003751 {
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07003752 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
3753 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
3754
3755 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
3756 {
3757 /* Generate the P2P Device Address. This consists of the device's
3758 * primary MAC address with the locally administered bit set.
3759 */
3760 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
3761 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003762 }
3763 else
3764 {
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07003765 hddLog(VOS_TRACE_LEVEL_FATAL,
3766 "%s: Failed to allocate mac_address for p2p_device",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003767 __func__);
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07003768 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003769 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003770
3771 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
3772 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
3773 if ( NULL == pP2pAdapter )
3774 {
3775 hddLog(VOS_TRACE_LEVEL_FATAL,
3776 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003777 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07003778 goto err_close_adapter;
3779 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003780#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003781 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003782#ifdef WLAN_SOFTAP_FEATURE
3783 }
3784#endif
3785
3786 if( pAdapter == NULL )
3787 {
3788 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
3789#ifdef ANI_BUS_TYPE_SDIO
3790 goto err_balstop;
3791#else
3792 goto err_clkvote;
3793#endif
3794 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003795
Jeff Johnson295189b2012-06-20 16:38:30 -07003796#ifdef WLAN_BTAMP_FEATURE
3797 vStatus = WLANBAP_Open(pVosContext);
3798 if(!VOS_IS_STATUS_SUCCESS(vStatus))
3799 {
3800 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3801 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07003802 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003803 }
3804
3805 vStatus = BSL_Init(pVosContext);
3806 if(!VOS_IS_STATUS_SUCCESS(vStatus))
3807 {
3808 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3809 "%s: Failed to Init BSL",__func__);
3810 goto err_bap_close;
3811 }
3812 vStatus = WLANBAP_Start(pVosContext);
3813 if (!VOS_IS_STATUS_SUCCESS(vStatus))
3814 {
3815 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3816 "%s: Failed to start TL",__func__);
3817 goto err_bap_close;
3818 }
3819
3820 pConfig = pHddCtx->cfg_ini;
3821 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
3822 status = WLANBAP_SetConfig(&btAmpConfig);
3823
3824#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07003825
Jeff Johnson295189b2012-06-20 16:38:30 -07003826#ifdef FEATURE_WLAN_SCAN_PNO
3827 /*SME must send channel update configuration to RIVA*/
3828 sme_UpdateChannelConfig(pHddCtx->hHal);
3829#endif
3830
3831#ifdef FEATURE_WLAN_INTEGRATED_SOC
3832 /* Register with platform driver as client for Suspend/Resume */
3833 status = hddRegisterPmOps(pHddCtx);
3834 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3835 {
3836 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
3837#ifdef WLAN_BTAMP_FEATURE
3838 goto err_bap_stop;
3839#else
Jeff Johnsone7245742012-09-05 17:12:55 -07003840 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003841#endif //WLAN_BTAMP_FEATURE
3842 }
3843
3844 /* Register TM level change handler function to the platform */
3845 status = hddDevTmRegisterNotifyCallback(pHddCtx);
3846 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3847 {
3848 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
3849 goto err_unregister_pmops;
3850 }
3851#endif
3852
3853 /* register for riva power on lock to platform driver */
3854 if (req_riva_power_on_lock("wlan"))
3855 {
3856 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
3857 __func__);
3858 goto err_unregister_pmops;
3859 }
3860
3861#ifdef CONFIG_HAS_EARLYSUSPEND
3862 // Register suspend/resume callbacks
3863 if(pHddCtx->cfg_ini->nEnableSuspend)
3864 {
3865 register_wlan_suspend();
3866 }
3867#endif
3868
3869 // register net device notifier for device change notification
3870 ret = register_netdevice_notifier(&hdd_netdev_notifier);
3871
3872 if(ret < 0)
3873 {
3874 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
3875 goto err_free_power_on_lock;
3876 }
3877
3878 //Initialize the nlink service
3879 if(nl_srv_init() != 0)
3880 {
3881 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
3882 goto err_reg_netdev;
3883 }
3884
3885 //Initialize the BTC service
3886 if(btc_activate_service(pHddCtx) != 0)
3887 {
3888 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
3889 goto err_nl_srv;
3890 }
3891
3892#ifdef PTT_SOCK_SVC_ENABLE
3893 //Initialize the PTT service
3894 if(ptt_sock_activate_svc(pHddCtx) != 0)
3895 {
3896 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
3897 goto err_nl_srv;
3898 }
3899#endif
3900
Jeff Johnson295189b2012-06-20 16:38:30 -07003901#ifdef CONFIG_HAS_EARLYSUSPEND
3902 hdd_register_mcast_bcast_filter(pHddCtx);
3903#endif
3904#ifdef CONFIG_CFG80211
3905#ifdef WLAN_SOFTAP_FEATURE
3906 if (VOS_STA_SAP_MODE != hdd_get_conparam())
3907#endif
3908 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07003909 /* Action frame registered in one adapter which will
3910 * applicable to all interfaces
3911 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07003912 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003913 }
3914#endif
3915
3916 mutex_init(&pHddCtx->sap_lock);
3917
3918 pHddCtx->isLoadUnloadInProgress = FALSE;
3919
Jeff Johnsone7245742012-09-05 17:12:55 -07003920#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3921 /* Initialize the wake lcok */
3922 wake_lock_init(&pHddCtx->rx_wake_lock,
3923 WAKE_LOCK_SUSPEND,
3924 "qcom_rx_wakelock");
3925#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003926 /* Initialize the wake lcok */
3927 wake_lock_init(&pHddCtx->sap_wake_lock,
3928 WAKE_LOCK_SUSPEND,
3929 "qcom_sap_wakelock");
Jeff Johnsone7245742012-09-05 17:12:55 -07003930
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003931 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
3932 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07003933
3934 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3935 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07003936
3937 // Initialize the restart logic
3938 wlan_hdd_restart_init(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003939
3940 goto success;
3941
3942err_nl_srv:
3943 nl_srv_exit();
3944
3945err_reg_netdev:
3946 unregister_netdevice_notifier(&hdd_netdev_notifier);
3947
3948err_free_power_on_lock:
3949 free_riva_power_on_lock("wlan");
3950
3951err_unregister_pmops:
3952 hddDevTmUnregisterNotifyCallback(pHddCtx);
3953 hddDeregisterPmOps(pHddCtx);
3954
3955#ifdef WLAN_BTAMP_FEATURE
3956err_bap_stop:
3957 WLANBAP_Stop(pVosContext);
3958#endif
3959
3960#ifdef WLAN_BTAMP_FEATURE
3961err_bap_close:
3962 WLANBAP_Close(pVosContext);
3963#endif
3964
Jeff Johnson295189b2012-06-20 16:38:30 -07003965err_close_adapter:
3966 hdd_close_all_adapters( pHddCtx );
3967
3968err_vosstop:
3969 vos_stop(pVosContext);
3970
3971err_vosclose:
3972 status = vos_sched_close( pVosContext );
3973 if (!VOS_IS_STATUS_SUCCESS(status)) {
3974 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3975 "%s: Failed to close VOSS Scheduler", __func__);
3976 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
3977 }
3978 vos_close(pVosContext );
3979
3980err_balstop:
3981#ifdef ANI_BUS_TYPE_SDIO
3982#ifndef ANI_MANF_DIAG
3983 wlan_hdd_enable_deepsleep(pHddCtx->pvosContext);
3984#endif
3985
3986 WLANBAL_Stop(pHddCtx->pvosContext);
3987 WLANBAL_SuspendChip(pHddCtx->pvosContext);
3988#endif
3989
3990#ifdef ANI_BUS_TYPE_SDIO
3991err_salstop:
3992 WLANSAL_Stop(pHddCtx->pvosContext);
3993
3994#endif
3995err_clkvote:
3996 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3997
3998#ifdef ANI_BUS_TYPE_SDIO
3999err_balclose:
4000 WLANBAL_Close(pHddCtx->pvosContext);
4001#endif // ANI_BUS_TYPE_SDIO
4002
4003err_wdclose:
4004 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4005 vos_watchdog_close(pVosContext);
4006
4007#ifdef CONFIG_CFG80211
4008err_wiphy_reg:
4009 wiphy_unregister(wiphy) ;
4010#endif
4011
4012err_config:
4013 kfree(pHddCtx->cfg_ini);
4014 pHddCtx->cfg_ini= NULL;
4015
4016err_free_hdd_context:
4017 hdd_allow_suspend();
4018#ifdef CONFIG_CFG80211
4019 wiphy_free(wiphy) ;
4020 //kfree(wdev) ;
4021#else
4022 vos_mem_free( pHddCtx );
4023#endif
4024 VOS_BUG(1);
4025
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004026 if (hdd_is_ssr_required())
4027 {
4028 /* WDI timeout had happened during load, so SSR is needed here */
4029 subsystem_restart("wcnss");
4030 msleep(5000);
4031 }
4032 hdd_set_ssr_required (VOS_FALSE);
4033
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004034 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004035
4036success:
4037 EXIT();
4038 return 0;
4039}
4040
4041/**---------------------------------------------------------------------------
4042
Jeff Johnson32d95a32012-09-10 13:15:23 -07004043 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004044
Jeff Johnson32d95a32012-09-10 13:15:23 -07004045 This is the driver entry point - called in different timeline depending
4046 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004047
4048 \param - None
4049
4050 \return - 0 for success, non zero for failure
4051
4052 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004053static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004054{
4055 VOS_STATUS status;
4056 v_CONTEXT_t pVosContext = NULL;
4057#ifdef ANI_BUS_TYPE_SDIO
4058 struct sdio_func *sdio_func_dev = NULL;
4059 unsigned int attempts = 0;
4060#endif // ANI_BUS_TYPE_SDIO
4061 struct device *dev = NULL;
4062 int ret_status = 0;
4063
4064 ENTER();
4065
Jeff Johnsone7245742012-09-05 17:12:55 -07004066#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07004067 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004068#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004069
4070 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4071 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4072
4073 //Power Up Libra WLAN card first if not already powered up
4074 status = vos_chipPowerUp(NULL,NULL,NULL);
4075 if (!VOS_IS_STATUS_SUCCESS(status))
4076 {
4077 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4078 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004079 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004080 }
4081
4082#ifdef ANI_BUS_TYPE_SDIO
4083 //SDIO Polling should be turned on for card detection. When using Android Wi-Fi GUI
4084 //users need not trigger SDIO polling explicitly. However when loading drivers via
4085 //command line (Adb shell), users must turn on SDIO polling prior to loading WLAN.
4086 do {
4087 sdio_func_dev = libra_getsdio_funcdev();
4088 if (NULL == sdio_func_dev) {
4089 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
4090 attempts++;
4091 }
4092 else {
4093 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
4094 dev = &sdio_func_dev->dev;
4095 break;
4096 }
4097
4098 if(attempts == 7)
4099 break;
4100
4101 msleep(250);
4102
4103 }while (attempts < 7);
4104
4105 //Retry to detect the card again by Powering Down the chip and Power up the chip
4106 //again. This retry is done to recover from CRC Error
4107 if (NULL == sdio_func_dev) {
4108
4109 attempts = 0;
4110
4111 //Vote off any PMIC voltage supplies
4112 vos_chipPowerDown(NULL, NULL, NULL);
4113
4114 msleep(1000);
4115
4116 //Power Up Libra WLAN card first if not already powered up
4117 status = vos_chipPowerUp(NULL,NULL,NULL);
4118 if (!VOS_IS_STATUS_SUCCESS(status))
4119 {
4120 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
4121 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004122 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004123 }
4124
4125 do {
4126 sdio_func_dev = libra_getsdio_funcdev();
4127 if (NULL == sdio_func_dev) {
4128 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
4129 attempts++;
4130 }
4131 else {
4132 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
4133 dev = &sdio_func_dev->dev;
4134 break;
4135 }
4136
4137 if(attempts == 2)
4138 break;
4139
4140 msleep(1000);
4141
4142 }while (attempts < 3);
4143 }
4144
4145#endif // ANI_BUS_TYPE_SDIO
4146
4147#ifdef ANI_BUS_TYPE_PCI
4148
4149 dev = wcnss_wlan_get_device();
4150
4151#endif // ANI_BUS_TYPE_PCI
4152
4153#ifdef ANI_BUS_TYPE_PLATFORM
4154 dev = wcnss_wlan_get_device();
4155#endif // ANI_BUS_TYPE_PLATFORM
4156
4157
4158 do {
4159 if (NULL == dev) {
4160 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4161 ret_status = -1;
4162 break;
4163 }
4164
4165#ifdef MEMORY_DEBUG
4166 vos_mem_init();
4167#endif
4168
4169#ifdef TIMER_MANAGER
4170 vos_timer_manager_init();
4171#endif
4172
4173 /* Preopen VOSS so that it is ready to start at least SAL */
4174 status = vos_preOpen(&pVosContext);
4175
4176 if (!VOS_IS_STATUS_SUCCESS(status))
4177 {
4178 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4179 ret_status = -1;
4180 break;
4181 }
4182
4183#ifdef ANI_BUS_TYPE_SDIO
4184 /* Now Open SAL */
4185 status = WLANSAL_Open(pVosContext, 0);
4186
4187 if(!VOS_IS_STATUS_SUCCESS(status))
4188 {
4189 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to open SAL", __func__);
4190
4191 /* If unable to open, cleanup and return failure */
4192 vos_preClose( &pVosContext );
4193 ret_status = -1;
4194 break;
4195 }
4196#endif // ANI_BUS_TYPE_SDIO
4197
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004198#ifndef MODULE
4199 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4200 */
4201 hdd_set_conparam((v_UINT_t)con_mode);
4202#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004203
4204 // Call our main init function
4205 if(hdd_wlan_startup(dev)) {
4206 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
4207 __func__);
4208#ifdef ANI_BUS_TYPE_SDIO
4209 WLANSAL_Close(pVosContext);
4210#endif // ANI_BUS_TYPE_SDIO
4211 vos_preClose( &pVosContext );
4212 ret_status = -1;
4213 break;
4214 }
4215
4216 /* Cancel the vote for XO Core ON
4217 * This is done here for safety purposes in case we re-initialize without turning
4218 * it OFF in any error scenario.
4219 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004220 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004221 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004222 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004223 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4224 {
4225 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4226 " Power consumed will be high\n");
4227 }
4228 } while (0);
4229
4230 if (0 != ret_status)
4231 {
4232 //Assert Deep sleep signal now to put Libra HW in lowest power state
4233 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4234 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4235
4236 //Vote off any PMIC voltage supplies
4237 vos_chipPowerDown(NULL, NULL, NULL);
4238#ifdef TIMER_MANAGER
4239 vos_timer_exit();
4240#endif
4241#ifdef MEMORY_DEBUG
4242 vos_mem_exit();
4243#endif
4244
Jeff Johnsone7245742012-09-05 17:12:55 -07004245#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07004246 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004247#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004248 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4249 }
4250 else
4251 {
4252 //Send WLAN UP indication to Nlink Service
4253 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4254
4255 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4256
4257 }
4258
4259 EXIT();
4260
4261 return ret_status;
4262}
4263
Jeff Johnson32d95a32012-09-10 13:15:23 -07004264/**---------------------------------------------------------------------------
4265
4266 \brief hdd_module_init() - Init Function
4267
4268 This is the driver entry point (invoked when module is loaded using insmod)
4269
4270 \param - None
4271
4272 \return - 0 for success, non zero for failure
4273
4274 --------------------------------------------------------------------------*/
4275#ifdef MODULE
4276static int __init hdd_module_init ( void)
4277{
4278 return hdd_driver_init();
4279}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004280#else /* #ifdef MODULE */
4281static int __init hdd_module_init ( void)
4282{
4283 /* Driver initialization is delayed to fwpath_changed_handler */
4284 return 0;
4285}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004286#endif /* #ifdef MODULE */
4287
Jeff Johnson295189b2012-06-20 16:38:30 -07004288
4289/**---------------------------------------------------------------------------
4290
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004291 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004292
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004293 This is the driver exit point (invoked when module is unloaded using rmmod
4294 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004295
4296 \param - None
4297
4298 \return - None
4299
4300 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004301static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004302{
4303 hdd_context_t *pHddCtx = NULL;
4304 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004305
4306 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4307
4308 //Get the global vos context
4309 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4310
4311 if(!pVosContext)
4312 {
4313 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4314 goto done;
4315 }
4316
4317 //Get the HDD context.
4318 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4319
4320 if(!pHddCtx)
4321 {
4322 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4323 }
4324 else
4325 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004326 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004327 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004328 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4329 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004330 }
4331
4332 pHddCtx->isLoadUnloadInProgress = TRUE;
4333 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4334
4335 //Do all the cleanup before deregistering the driver
4336 hdd_wlan_exit(pHddCtx);
4337 }
4338
4339#ifdef ANI_BUS_TYPE_SDIO
4340 WLANSAL_Close(pVosContext);
4341#endif // ANI_BUS_TYPE_SDIO
4342
4343 vos_preClose( &pVosContext );
4344
4345#ifdef TIMER_MANAGER
4346 vos_timer_exit();
4347#endif
4348#ifdef MEMORY_DEBUG
4349 vos_mem_exit();
4350#endif
4351
4352done:
Jeff Johnsone7245742012-09-05 17:12:55 -07004353#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07004354 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004355#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004356 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4357}
4358
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004359/**---------------------------------------------------------------------------
4360
4361 \brief hdd_module_exit() - Exit function
4362
4363 This is the driver exit point (invoked when module is unloaded using rmmod)
4364
4365 \param - None
4366
4367 \return - None
4368
4369 --------------------------------------------------------------------------*/
4370static void __exit hdd_module_exit(void)
4371{
4372 hdd_driver_exit();
4373}
4374
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004375#ifdef MODULE
4376static int fwpath_changed_handler(const char *kmessage,
4377 struct kernel_param *kp)
4378{
4379 /* nothing to do when driver is DLKM */
4380 return 0;
4381}
4382
4383static int con_mode_handler(const char *kmessage,
4384 struct kernel_param *kp)
4385{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004386 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004387}
4388#else /* #ifdef MODULE */
4389/**---------------------------------------------------------------------------
4390
4391 \brief fwpath_changed_handler() - Handler Function
4392
4393 This is the driver entry point
4394 - delayed driver initialization when driver is statically linked
4395 - invoked when module parameter fwpath is modified from userpspace to signal
4396 initializing the WLAN driver
4397
4398 \return - 0 for success, non zero for failure
4399
4400 --------------------------------------------------------------------------*/
4401static int fwpath_changed_handler(const char *kmessage,
4402 struct kernel_param *kp)
4403{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004404 int ret_status;
4405
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004406 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004407 ret_status = hdd_driver_init();
4408 wlan_hdd_inited = ret_status ? 0 : 1;
4409 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004410 }
4411
4412 hdd_driver_exit();
4413
4414 msleep(200);
4415
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004416 ret_status = hdd_driver_init();
4417 wlan_hdd_inited = ret_status ? 0 : 1;
4418 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004419}
4420
Jeff Johnson295189b2012-06-20 16:38:30 -07004421/**---------------------------------------------------------------------------
4422
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004423 \brief con_mode_handler() -
4424
4425 Handler function for module param con_mode when it is changed by userspace
4426 Dynamically linked - do nothing
4427 Statically linked - exit and init driver, as in rmmod and insmod
4428
4429 \param -
4430
4431 \return -
4432
4433 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004434static int con_mode_handler(const char *kmessage,
4435 struct kernel_param *kp)
4436{
4437 int ret = param_set_int(kmessage, kp);
4438
4439 if (ret)
4440 return ret;
4441
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004442 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004443}
4444#endif /* #ifdef MODULE */
4445
4446/**---------------------------------------------------------------------------
4447
Jeff Johnson295189b2012-06-20 16:38:30 -07004448 \brief hdd_get_conparam() -
4449
4450 This is the driver exit point (invoked when module is unloaded using rmmod)
4451
4452 \param - None
4453
4454 \return - tVOS_CON_MODE
4455
4456 --------------------------------------------------------------------------*/
4457tVOS_CON_MODE hdd_get_conparam ( void )
4458{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004459#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004460 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004461#else
4462 return (tVOS_CON_MODE)curr_con_mode;
4463#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004464}
4465void hdd_set_conparam ( v_UINT_t newParam )
4466{
4467 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004468#ifndef MODULE
4469 curr_con_mode = con_mode;
4470#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004471}
4472/**---------------------------------------------------------------------------
4473
4474 \brief hdd_softap_sta_deauth() - function
4475
4476 This to take counter measure to handle deauth req from HDD
4477
4478 \param - pAdapter - Pointer to the HDD
4479
4480 \param - enable - boolean value
4481
4482 \return - None
4483
4484 --------------------------------------------------------------------------*/
4485
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004486VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004487{
Jeff Johnson295189b2012-06-20 16:38:30 -07004488 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004489 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004490#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
4491 tHalHandle hHalHandle;
4492#endif
4493
4494 ENTER();
4495
4496 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4497
4498 //Ignore request to deauth bcmc station
4499 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004500 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004501
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004502 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004503
4504 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004505 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004506}
4507
4508/**---------------------------------------------------------------------------
4509
4510 \brief hdd_softap_sta_disassoc() - function
4511
4512 This to take counter measure to handle deauth req from HDD
4513
4514 \param - pAdapter - Pointer to the HDD
4515
4516 \param - enable - boolean value
4517
4518 \return - None
4519
4520 --------------------------------------------------------------------------*/
4521
4522void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4523{
4524 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4525
4526 ENTER();
4527
4528 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4529
4530 //Ignore request to disassoc bcmc station
4531 if( pDestMacAddress[0] & 0x1 )
4532 return;
4533
4534 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4535}
4536
4537void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4538{
4539 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4540
4541 ENTER();
4542
4543 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4544
4545 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4546}
4547
Jeff Johnson295189b2012-06-20 16:38:30 -07004548/**---------------------------------------------------------------------------
4549 *
4550 * \brief hdd_get__concurrency_mode() -
4551 *
4552 *
4553 * \param - None
4554 *
4555 * \return - CONCURRENCY MODE
4556 *
4557 * --------------------------------------------------------------------------*/
4558tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4559{
4560 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4561 hdd_context_t *pHddCtx;
4562
4563 if (NULL != pVosContext)
4564 {
4565 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4566 if (NULL != pHddCtx)
4567 {
4568 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4569 }
4570 }
4571
4572 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004573 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004574 return VOS_STA;
4575}
4576
4577/* Decide whether to allow/not the apps power collapse.
4578 * Allow apps power collapse if we are in connected state.
4579 * if not, allow only if we are in IMPS */
4580v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4581{
4582 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4583 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4584 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4585 hdd_adapter_t *pAdapter = NULL;
4586 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004587 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004588
4589#ifdef WLAN_SOFTAP_FEATURE
4590 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4591 return TRUE;
4592#endif
4593
Yathish9f22e662012-12-10 14:21:35 -08004594 concurrent_state = hdd_get_concurrency_mode();
4595
4596#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4597 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4598 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4599 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4600 return TRUE;
4601#endif
4602
Jeff Johnson295189b2012-06-20 16:38:30 -07004603 /*loop through all adapters. TBD fix for Concurrency */
4604 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4605 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4606 {
4607 pAdapter = pAdapterNode->pAdapter;
4608 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4609 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4610 {
4611 if ((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
4612 && (pmcState != IMPS && pmcState != BMPS
4613 && pmcState != STOPPED && pmcState != STANDBY))
4614 {
4615 return FALSE;
4616 }
4617 }
4618 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4619 pAdapterNode = pNext;
4620 }
4621 return TRUE;
4622}
4623
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08004624/* Decides whether to send suspend notification to Riva
4625 * if any adapter is in BMPS; then it is required */
4626v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
4627{
4628 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
4629 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4630
4631 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
4632 {
4633 return TRUE;
4634 }
4635 return FALSE;
4636}
4637
Jeff Johnson295189b2012-06-20 16:38:30 -07004638void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4639{
4640 switch(mode)
4641 {
4642 case WLAN_HDD_INFRA_STATION:
4643#ifdef WLAN_FEATURE_P2P
4644 case WLAN_HDD_P2P_CLIENT:
4645 case WLAN_HDD_P2P_GO:
4646#endif
4647 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07004648 pHddCtx->concurrency_mode |= (1 << mode);
4649 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07004650 break;
4651 default:
4652 break;
4653
4654 }
4655 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4656 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4657}
4658
4659
4660void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
4661{
4662 switch(mode)
4663 {
4664 case WLAN_HDD_INFRA_STATION:
4665#ifdef WLAN_FEATURE_P2P
4666 case WLAN_HDD_P2P_CLIENT:
4667 case WLAN_HDD_P2P_GO:
4668#endif
4669 case WLAN_HDD_SOFTAP:
4670 pHddCtx->no_of_sessions[mode]--;
4671 if (!(pHddCtx->no_of_sessions[mode]))
4672 pHddCtx->concurrency_mode &= (~(1 << mode));
4673 break;
4674 default:
4675 break;
4676 }
4677 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
4678 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
4679}
4680
Jeff Johnsone7245742012-09-05 17:12:55 -07004681/**---------------------------------------------------------------------------
4682 *
4683 * \brief wlan_hdd_restart_init
4684 *
4685 * This function initalizes restart timer/flag. An internal function.
4686 *
4687 * \param - pHddCtx
4688 *
4689 * \return - None
4690 *
4691 * --------------------------------------------------------------------------*/
4692
4693static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
4694{
4695 /* Initialize */
4696 pHddCtx->hdd_restart_retries = 0;
4697 atomic_set(&pHddCtx->isRestartInProgress, 0);
4698 vos_timer_init(&pHddCtx->hdd_restart_timer,
4699 VOS_TIMER_TYPE_SW,
4700 wlan_hdd_restart_timer_cb,
4701 pHddCtx);
4702}
4703/**---------------------------------------------------------------------------
4704 *
4705 * \brief wlan_hdd_restart_deinit
4706 *
4707 * This function cleans up the resources used. An internal function.
4708 *
4709 * \param - pHddCtx
4710 *
4711 * \return - None
4712 *
4713 * --------------------------------------------------------------------------*/
4714
4715static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
4716{
4717
4718 VOS_STATUS vos_status;
4719 /* Block any further calls */
4720 atomic_set(&pHddCtx->isRestartInProgress, 1);
4721 /* Cleanup */
4722 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
4723 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004724 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004725 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
4726 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004727 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07004728
4729}
4730
4731/**---------------------------------------------------------------------------
4732 *
4733 * \brief wlan_hdd_framework_restart
4734 *
4735 * This function uses a cfg80211 API to start a framework initiated WLAN
4736 * driver module unload/load.
4737 *
4738 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
4739 *
4740 *
4741 * \param - pHddCtx
4742 *
4743 * \return - VOS_STATUS_SUCCESS: Success
4744 * VOS_STATUS_E_EMPTY: Adapter is Empty
4745 * VOS_STATUS_E_NOMEM: No memory
4746
4747 * --------------------------------------------------------------------------*/
4748
4749static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
4750{
4751 VOS_STATUS status = VOS_STATUS_SUCCESS;
4752 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4753 int len = (sizeof (struct ieee80211_mgmt));
4754 struct ieee80211_mgmt *mgmt = NULL;
4755
4756 /* Prepare the DEAUTH managment frame with reason code */
4757 mgmt = kzalloc(len, GFP_KERNEL);
4758 if(mgmt == NULL)
4759 {
4760 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08004761 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07004762 return VOS_STATUS_E_NOMEM;
4763 }
4764 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
4765
4766 /* Iterate over all adapters/devices */
4767 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4768 do
4769 {
4770 if( (status == VOS_STATUS_SUCCESS) &&
4771 pAdapterNode &&
4772 pAdapterNode->pAdapter)
4773 {
4774 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
4775 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
4776 pAdapterNode->pAdapter->dev->name,
4777 pAdapterNode->pAdapter->device_mode,
4778 pHddCtx->hdd_restart_retries + 1);
4779 /*
4780 * CFG80211 event to restart the driver
4781 *
4782 * 'cfg80211_send_unprot_deauth' sends a
4783 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
4784 * of SME(Linux Kernel) state machine.
4785 *
4786 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
4787 * the driver.
4788 *
4789 */
4790
4791 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
4792 }
4793 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4794 pAdapterNode = pNext;
4795 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
4796
4797
4798 /* Free the allocated management frame */
4799 kfree(mgmt);
4800
4801 /* Retry until we unload or reach max count */
4802 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
4803 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
4804
4805 return status;
4806
4807}
4808/**---------------------------------------------------------------------------
4809 *
4810 * \brief wlan_hdd_restart_timer_cb
4811 *
4812 * Restart timer callback. An internal function.
4813 *
4814 * \param - User data:
4815 *
4816 * \return - None
4817 *
4818 * --------------------------------------------------------------------------*/
4819
4820void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
4821{
4822 hdd_context_t *pHddCtx = usrDataForCallback;
4823 wlan_hdd_framework_restart(pHddCtx);
4824 return;
4825
4826}
4827
4828
4829/**---------------------------------------------------------------------------
4830 *
4831 * \brief wlan_hdd_restart_driver
4832 *
4833 * This function sends an event to supplicant to restart the WLAN driver.
4834 *
4835 * This function is called from vos_wlanRestart.
4836 *
4837 * \param - pHddCtx
4838 *
4839 * \return - VOS_STATUS_SUCCESS: Success
4840 * VOS_STATUS_E_EMPTY: Adapter is Empty
4841 * VOS_STATUS_E_ALREADY: Request already in progress
4842
4843 * --------------------------------------------------------------------------*/
4844VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
4845{
4846 VOS_STATUS status = VOS_STATUS_SUCCESS;
4847
4848 /* A tight check to make sure reentrancy */
4849 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
4850 {
4851 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
4852 "%s: WLAN restart is already in progress", __func__);
4853
4854 return VOS_STATUS_E_ALREADY;
4855 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004856 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07004857 * the reset interrupt. If it is DLKM, then use restart API
4858 */
4859#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07004860 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07004861#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08004862#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07004863 wcnss_reset_intr();
4864#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08004865#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07004866
Jeff Johnsone7245742012-09-05 17:12:55 -07004867 return status;
4868}
4869
4870
Jeff Johnson295189b2012-06-20 16:38:30 -07004871//Register the module init/exit functions
4872module_init(hdd_module_init);
4873module_exit(hdd_module_exit);
4874
4875MODULE_LICENSE("Dual BSD/GPL");
4876MODULE_AUTHOR("Qualcomm Atheros, Inc.");
4877MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
4878
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004879module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
4880 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07004881
4882module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
4883 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);