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