blob: 941ae7ac27d6e39b05e042da4f67549a3f5fc14c [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);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800190void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700191
Jeff Johnson295189b2012-06-20 16:38:30 -0700192v_U16_t hdd_select_queue(struct net_device *dev,
193 struct sk_buff *skb);
194
195#ifdef WLAN_FEATURE_PACKET_FILTERING
196static void hdd_set_multicast_list(struct net_device *dev);
197#endif
198
199void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
200
201extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
202
203static int hdd_netdev_notifier_call(struct notifier_block * nb,
204 unsigned long state,
205 void *ndev)
206{
207 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700208 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
209 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -0700210#ifdef WLAN_BTAMP_FEATURE
211 VOS_STATUS status;
212 hdd_context_t *pHddCtx;
213#endif
214
215 //Make sure that this callback corresponds to our device.
216 if((strncmp( dev->name, "wlan", 4 )) &&
Jeff Johnsone7245742012-09-05 17:12:55 -0700217 (strncmp( dev->name, "p2p", 3))
Jeff Johnson295189b2012-06-20 16:38:30 -0700218 )
219 return NOTIFY_DONE;
220
221#ifdef CONFIG_CFG80211
222 if (!dev->ieee80211_ptr)
223 return NOTIFY_DONE;
224#endif
225
Jeff Johnson295189b2012-06-20 16:38:30 -0700226
227 if(NULL == pAdapter)
228 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800229 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700230 VOS_ASSERT(0);
231 return NOTIFY_DONE;
232 }
233
234 hddLog(VOS_TRACE_LEVEL_INFO,"%s: New Net Device State = %lu", __func__, state);
235
236 switch (state) {
237 case NETDEV_REGISTER:
238 break;
239
240 case NETDEV_UNREGISTER:
241 break;
242
243 case NETDEV_UP:
244 break;
245
246 case NETDEV_DOWN:
247 break;
248
249 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700250 if(TRUE == pAdapter->isLinkUpSvcNeeded)
251 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252 break;
253
254 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700255 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 {
257 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800258 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700259 hdd_abort_mac_scan(pAdapter->pHddCtx);
260 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800261 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700262 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
263 if(!result)
264 {
265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800266 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700267 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700268 }
269 }
270 else
271 {
272 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700273 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 }
275#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700276 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 status = WLANBAP_StopAmp();
278 if(VOS_STATUS_SUCCESS != status )
279 {
280 pHddCtx->isAmpAllowed = VOS_TRUE;
281 hddLog(VOS_TRACE_LEVEL_FATAL,
282 "%s: Failed to stop AMP", __func__);
283 }
284 else
285 {
286 //a state m/c implementation in PAL is TBD to avoid this delay
287 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700288 if ( pHddCtx->isAmpAllowed )
289 {
290 WLANBAP_DeregisterFromHCI();
291 pHddCtx->isAmpAllowed = VOS_FALSE;
292 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700293 }
294#endif //WLAN_BTAMP_FEATURE
295 break;
296
297 default:
298 break;
299 }
300
301 return NOTIFY_DONE;
302}
303
304struct notifier_block hdd_netdev_notifier = {
305 .notifier_call = hdd_netdev_notifier_call,
306};
307
308/*---------------------------------------------------------------------------
309 * Function definitions
310 *-------------------------------------------------------------------------*/
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800311int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700312void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
313void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700314//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700315static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700316#ifndef MODULE
317/* current con_mode - used only for statically linked driver
318 * con_mode is changed by userspace to indicate a mode change which will
319 * result in calling the module exit and init functions. The module
320 * exit function will clean up based on the value of con_mode prior to it
321 * being changed by userspace. So curr_con_mode records the current con_mode
322 * for exit when con_mode becomes the next mode for init
323 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700324static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700325#endif
326
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800327/**---------------------------------------------------------------------------
328
329 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
330
331 Called immediately after the cfg.ini is read in order to configure
332 the desired trace levels.
333
334 \param - moduleId - module whose trace level is being configured
335 \param - bitmask - bitmask of log levels to be enabled
336
337 \return - void
338
339 --------------------------------------------------------------------------*/
340static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
341{
342 wpt_tracelevel level;
343
344 /* if the bitmask is the default value, then a bitmask was not
345 specified in cfg.ini, so leave the logging level alone (it
346 will remain at the "compiled in" default value) */
347 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
348 {
349 return;
350 }
351
352 /* a mask was specified. start by disabling all logging */
353 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
354
355 /* now cycle through the bitmask until all "set" bits are serviced */
356 level = VOS_TRACE_LEVEL_FATAL;
357 while (0 != bitmask)
358 {
359 if (bitmask & 1)
360 {
361 vos_trace_setValue(moduleId, level, 1);
362 }
363 level++;
364 bitmask >>= 1;
365 }
366}
367
368
Jeff Johnson295189b2012-06-20 16:38:30 -0700369#ifdef FEATURE_WLAN_INTEGRATED_SOC
370/**---------------------------------------------------------------------------
371
372 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
373
374 Called immediately after the cfg.ini is read in order to configure
375 the desired trace levels in the WDI.
376
377 \param - moduleId - module whose trace level is being configured
378 \param - bitmask - bitmask of log levels to be enabled
379
380 \return - void
381
382 --------------------------------------------------------------------------*/
383static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
384{
385 wpt_tracelevel level;
386
387 /* if the bitmask is the default value, then a bitmask was not
388 specified in cfg.ini, so leave the logging level alone (it
389 will remain at the "compiled in" default value) */
390 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
391 {
392 return;
393 }
394
395 /* a mask was specified. start by disabling all logging */
396 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
397
398 /* now cycle through the bitmask until all "set" bits are serviced */
399 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
400 while (0 != bitmask)
401 {
402 if (bitmask & 1)
403 {
404 wpalTraceSetLevel(moduleId, level, 1);
405 }
406 level++;
407 bitmask >>= 1;
408 }
409}
410#endif /* FEATURE_WLAN_INTEGRATED_SOC */
411
412int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
413{
414 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
415 hdd_priv_data_t priv_data;
416 tANI_U8 *command = NULL;
417 int ret = 0;
418
419 if (NULL == pAdapter)
420 {
421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700422 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700423 ret = -ENODEV;
424 goto exit;
425 }
426
Jeff Johnsone7245742012-09-05 17:12:55 -0700427 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700428 {
429 ret = -EINVAL;
430 goto exit;
431 }
432
433 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
434 {
435 ret = -EFAULT;
436 goto exit;
437 }
438
439 command = kmalloc(priv_data.total_len, GFP_KERNEL);
440 if (!command)
441 {
442 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700443 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700444 ret = -ENOMEM;
445 goto exit;
446 }
447
448 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
449 {
450 ret = -EFAULT;
451 goto exit;
452 }
453
454 if ((SIOCDEVPRIVATE + 1) == cmd)
455 {
456 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
457
458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700459 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700460
461 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
462 {
463 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
464 sizeof(tSirMacAddr)))
465 {
466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700467 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700468 ret = -EFAULT;
469 }
470 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700471 else if(strncmp(priv_data.buf, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700472 {
473 tANI_U8 *ptr = (tANI_U8*)priv_data.buf ;
474 int ret = 0 ;
475
476 /* Change band request received */
477
478 /* First 8 bytes will have "SETBAND " and
479 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700481 "%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 -0700482
483 /* Change band request received */
484 ret = hdd_setBand_helper(dev, ptr);
485 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700486 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
487 {
488 char *country_code;
489
490 country_code = command + 8;
491 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
492 pAdapter, pHddCtx->pvosContext);
493 if( 0 != ret )
494 {
495 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
496 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
497
498 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700499 }
500 /*
501 command should be a string having format
502 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
503 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -0700504 else if(strncmp(priv_data.buf, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700505 {
506 tANI_U8 *ptr = (tANI_U8*)priv_data.buf;
507
508 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700509 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700510
511 ret = sapSetPreferredChannel(dev, ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700512 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800513 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
514 {
515 int suspend = 0;
516 tANI_U8 *ptr = (tANI_U8*)command + 15;
517
518 suspend = *ptr - '0';
519 hdd_set_wlan_suspend_mode(suspend);
520 }
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700521 else {
522 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
523 __func__, command);
524 }
525
Jeff Johnson295189b2012-06-20 16:38:30 -0700526 }
527exit:
528 if (command)
529 {
530 kfree(command);
531 }
532 return ret;
533}
534
535/**---------------------------------------------------------------------------
536
537 \brief hdd_open() - HDD Open function
538
539 This is called in response to ifconfig up
540
541 \param - dev Pointer to net_device structure
542
543 \return - 0 for success non-zero for failure
544
545 --------------------------------------------------------------------------*/
546int hdd_open (struct net_device *dev)
547{
548 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
549 hdd_context_t *pHddCtx;
550 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
551 VOS_STATUS status;
552 v_BOOL_t in_standby = TRUE;
553
554 if (NULL == pAdapter)
555 {
556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700557 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700558 return -ENODEV;
559 }
560
561 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
562 if (NULL == pHddCtx)
563 {
564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700565 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700566 return -ENODEV;
567 }
568
569 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
570 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
571 {
572 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
573 {
574 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
575 "standby", __func__, pAdapter->device_mode);
576 in_standby = FALSE;
577 break;
578 }
579 else
580 {
581 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
582 pAdapterNode = pNext;
583 }
584 }
585
586 if (TRUE == in_standby)
587 {
588 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
589 {
590 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
591 "wlan out of power save", __func__);
592 return -EINVAL;
593 }
594 }
595
596 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
597 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
598 {
599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700600 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700601 /* Enable TX queues only when we are connected */
602 netif_tx_start_all_queues(dev);
603 }
604
605 return 0;
606}
607
608int hdd_mon_open (struct net_device *dev)
609{
610 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
611
612 if(pAdapter == NULL) {
613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700614 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -0800615 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -0700616 }
617
618 netif_start_queue(dev);
619
620 return 0;
621}
622/**---------------------------------------------------------------------------
623
624 \brief hdd_stop() - HDD stop function
625
626 This is called in response to ifconfig down
627
628 \param - dev Pointer to net_device structure
629
630 \return - 0 for success non-zero for failure
631
632 --------------------------------------------------------------------------*/
633
634int hdd_stop (struct net_device *dev)
635{
636 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
637 hdd_context_t *pHddCtx;
638 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
639 VOS_STATUS status;
640 v_BOOL_t enter_standby = TRUE;
641
642 ENTER();
643
644 if (NULL == pAdapter)
645 {
646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700647 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700648 return -ENODEV;
649 }
650
651 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
652 if (NULL == pHddCtx)
653 {
654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700655 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700656 return -ENODEV;
657 }
658
659 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
660 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
661 netif_tx_disable(pAdapter->dev);
662 netif_carrier_off(pAdapter->dev);
663
664
665 /* SoftAP ifaces should never go in power save mode
666 making sure same here. */
667 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
668 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
669#ifdef WLAN_FEATURE_P2P
670 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
671#endif
672 )
673 {
674 /* SoftAP mode, so return from here */
675 EXIT();
676 return 0;
677 }
678
679 /* Find if any iface is up then
680 if any iface is up then can't put device to sleep/ power save mode. */
681 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
682 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
683 {
684 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
685 {
686 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
687 "put device to sleep", __func__, pAdapter->device_mode);
688 enter_standby = FALSE;
689 break;
690 }
691 else
692 {
693 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
694 pAdapterNode = pNext;
695 }
696 }
697
698 if (TRUE == enter_standby)
699 {
700 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
701 "entering standby", __func__);
702 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
703 {
704 /*log and return success*/
705 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
706 "wlan in power save", __func__);
707 }
708 }
709
710 EXIT();
711 return 0;
712}
713
714/**---------------------------------------------------------------------------
715
716 \brief hdd_uninit() - HDD uninit function
717
718 This is called during the netdev unregister to uninitialize all data
719associated with the device
720
721 \param - dev Pointer to net_device structure
722
723 \return - void
724
725 --------------------------------------------------------------------------*/
726static void hdd_uninit (struct net_device *dev)
727{
728 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
729
730 ENTER();
731
732 do
733 {
734 if (NULL == pAdapter)
735 {
736 hddLog(VOS_TRACE_LEVEL_FATAL,
737 "%s: NULL pAdapter", __func__);
738 break;
739 }
740
741 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
742 {
743 hddLog(VOS_TRACE_LEVEL_FATAL,
744 "%s: Invalid magic", __func__);
745 break;
746 }
747
748 if (NULL == pAdapter->pHddCtx)
749 {
750 hddLog(VOS_TRACE_LEVEL_FATAL,
751 "%s: NULL pHddCtx", __func__);
752 break;
753 }
754
755 if (dev != pAdapter->dev)
756 {
757 hddLog(VOS_TRACE_LEVEL_FATAL,
758 "%s: Invalid device reference", __func__);
759 /* we haven't validated all cases so let this go for now */
760 }
761
762 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
763
764 /* after uninit our adapter structure will no longer be valid */
765 pAdapter->dev = NULL;
766 pAdapter->magic = 0;
767 } while (0);
768
769 EXIT();
770}
771
772/**---------------------------------------------------------------------------
773
774 \brief hdd_release_firmware() -
775
776 This function calls the release firmware API to free the firmware buffer.
777
778 \param - pFileName Pointer to the File Name.
779 pCtx - Pointer to the adapter .
780
781
782 \return - 0 for success, non zero for failure
783
784 --------------------------------------------------------------------------*/
785
786VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
787{
788 VOS_STATUS status = VOS_STATUS_SUCCESS;
789 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
790 ENTER();
791
792
793 if (!strcmp(WLAN_FW_FILE, pFileName)) {
794
795 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
796
797 if(pHddCtx->fw) {
798 release_firmware(pHddCtx->fw);
799 pHddCtx->fw = NULL;
800 }
801 else
802 status = VOS_STATUS_E_FAILURE;
803 }
804 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
805 if(pHddCtx->nv) {
806 release_firmware(pHddCtx->nv);
807 pHddCtx->nv = NULL;
808 }
809 else
810 status = VOS_STATUS_E_FAILURE;
811
812 }
813
814 EXIT();
815 return status;
816}
817
818/**---------------------------------------------------------------------------
819
820 \brief hdd_request_firmware() -
821
822 This function reads the firmware file using the request firmware
823 API and returns the the firmware data and the firmware file size.
824
825 \param - pfileName - Pointer to the file name.
826 - pCtx - Pointer to the adapter .
827 - ppfw_data - Pointer to the pointer of the firmware data.
828 - pSize - Pointer to the file size.
829
830 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
831
832 --------------------------------------------------------------------------*/
833
834
835VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
836{
837 int status;
838 VOS_STATUS retval = VOS_STATUS_SUCCESS;
839 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
840 ENTER();
841
842 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
843
844 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
845
846 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
847 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
848 __func__, pfileName);
849 retval = VOS_STATUS_E_FAILURE;
850 }
851
852 else {
853 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
854 *pSize = pHddCtx->fw->size;
855 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
856 __func__, *pSize);
857 }
858 }
859 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
860
861 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
862
863 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
864 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
865 __func__, pfileName);
866 retval = VOS_STATUS_E_FAILURE;
867 }
868
869 else {
870 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
871 *pSize = pHddCtx->nv->size;
872 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
873 __func__, *pSize);
874 }
875 }
876
877 EXIT();
878 return retval;
879}
880/**---------------------------------------------------------------------------
881 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
882
883 This is the function invoked by SME to inform the result of a full power
884 request issued by HDD
885
886 \param - callbackcontext - Pointer to cookie
887 status - result of request
888
889 \return - None
890
891--------------------------------------------------------------------------*/
892void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
893{
894 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
895
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700896 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -0700897 if(&pHddCtx->full_pwr_comp_var)
898 {
899 complete(&pHddCtx->full_pwr_comp_var);
900 }
901}
902
903/**---------------------------------------------------------------------------
904
905 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
906
907 This is the function invoked by SME to inform the result of BMPS
908 request issued by HDD
909
910 \param - callbackcontext - Pointer to cookie
911 status - result of request
912
913 \return - None
914
915--------------------------------------------------------------------------*/
916void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
917{
918
919 struct completion *completion_var = (struct completion*) callbackContext;
920
921 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
922 if(completion_var != NULL)
923 {
924 complete(completion_var);
925 }
926}
927
928/**---------------------------------------------------------------------------
929
930 \brief hdd_get_cfg_file_size() -
931
932 This function reads the configuration file using the request firmware
933 API and returns the configuration file size.
934
935 \param - pCtx - Pointer to the adapter .
936 - pFileName - Pointer to the file name.
937 - pBufSize - Pointer to the buffer size.
938
939 \return - 0 for success, non zero for failure
940
941 --------------------------------------------------------------------------*/
942
943VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
944{
945 int status;
946 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
947
948 ENTER();
949
950 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
951
952 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
953 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
954 status = VOS_STATUS_E_FAILURE;
955 }
956 else {
957 *pBufSize = pHddCtx->fw->size;
958 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
959 release_firmware(pHddCtx->fw);
960 pHddCtx->fw = NULL;
961 }
962
963 EXIT();
964 return VOS_STATUS_SUCCESS;
965}
966
967/**---------------------------------------------------------------------------
968
969 \brief hdd_read_cfg_file() -
970
971 This function reads the configuration file using the request firmware
972 API and returns the cfg data and the buffer size of the configuration file.
973
974 \param - pCtx - Pointer to the adapter .
975 - pFileName - Pointer to the file name.
976 - pBuffer - Pointer to the data buffer.
977 - pBufSize - Pointer to the buffer size.
978
979 \return - 0 for success, non zero for failure
980
981 --------------------------------------------------------------------------*/
982
983VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
984 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
985{
986 int status;
987 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
988
989 ENTER();
990
991 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
992
993 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
994 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
995 return VOS_STATUS_E_FAILURE;
996 }
997 else {
998 if(*pBufSize != pHddCtx->fw->size) {
999 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
1000 "file size", __func__);
1001 release_firmware(pHddCtx->fw);
1002 pHddCtx->fw = NULL;
1003 return VOS_STATUS_E_FAILURE;
1004 }
1005 else {
1006 if(pBuffer) {
1007 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
1008 }
1009 release_firmware(pHddCtx->fw);
1010 pHddCtx->fw = NULL;
1011 }
1012 }
1013
1014 EXIT();
1015
1016 return VOS_STATUS_SUCCESS;
1017}
1018
1019/**---------------------------------------------------------------------------
1020
1021 \brief hdd_set_mac_addr_cb() -
1022
1023 This function is the call back function for setting the station
1024 mac adrress called by ccm module to indicate the
1025 success/failure result.
1026
1027 \param - hHal - Pointer to the hal module.
1028 - result - returns the result of the set mac address.
1029
1030 \return - void
1031
1032 --------------------------------------------------------------------------*/
1033#ifndef FEATURE_WLAN_INTEGRATED_SOC
1034static void hdd_set_mac_addr_cb( tHalHandle hHal, tANI_S32 result )
1035{
1036 // ignore the STA_ID response for now.
1037
1038 VOS_ASSERT( CCM_IS_RESULT_SUCCESS( result ) );
1039}
1040#endif
1041
1042
1043/**---------------------------------------------------------------------------
1044
1045 \brief hdd_set_mac_address() -
1046
1047 This function sets the user specified mac address using
1048 the command ifconfig wlanX hw ether <mac adress>.
1049
1050 \param - dev - Pointer to the net device.
1051 - addr - Pointer to the sockaddr.
1052 \return - 0 for success, non zero for failure
1053
1054 --------------------------------------------------------------------------*/
1055
1056static int hdd_set_mac_address(struct net_device *dev, void *addr)
1057{
1058 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1059 struct sockaddr *psta_mac_addr = addr;
1060 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1061
1062 ENTER();
1063
1064 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1065
1066#ifdef HDD_SESSIONIZE
1067 // set the MAC address though the STA ID CFG.
1068 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
1069 (v_U8_t *)&pAdapter->macAddressCurrent,
1070 sizeof( pAdapter->macAddressCurrent ),
1071 hdd_set_mac_addr_cb, VOS_FALSE );
1072#endif
1073
1074 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1075
1076 EXIT();
1077 return halStatus;
1078}
1079
1080tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
1081{
1082 int i;
1083 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1084 {
1085 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
1086 break;
1087 }
1088
1089 if( VOS_MAX_CONCURRENCY_PERSONA == i)
1090 return NULL;
1091
1092 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
1093 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
1094}
1095
1096void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
1097{
1098 int i;
1099 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1100 {
1101 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
1102 {
1103 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
1104 break;
1105 }
1106 }
1107 return;
1108}
1109
1110#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1111 static struct net_device_ops wlan_drv_ops = {
1112 .ndo_open = hdd_open,
1113 .ndo_stop = hdd_stop,
1114 .ndo_uninit = hdd_uninit,
1115 .ndo_start_xmit = hdd_hard_start_xmit,
1116 .ndo_tx_timeout = hdd_tx_timeout,
1117 .ndo_get_stats = hdd_stats,
1118 .ndo_do_ioctl = hdd_ioctl,
1119 .ndo_set_mac_address = hdd_set_mac_address,
1120 .ndo_select_queue = hdd_select_queue,
1121#ifdef WLAN_FEATURE_PACKET_FILTERING
1122#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
1123 .ndo_set_rx_mode = hdd_set_multicast_list,
1124#else
1125 .ndo_set_multicast_list = hdd_set_multicast_list,
1126#endif //LINUX_VERSION_CODE
1127#endif
1128 };
1129#ifdef CONFIG_CFG80211
1130 static struct net_device_ops wlan_mon_drv_ops = {
1131 .ndo_open = hdd_mon_open,
1132 .ndo_stop = hdd_stop,
1133 .ndo_uninit = hdd_uninit,
1134 .ndo_start_xmit = hdd_mon_hard_start_xmit,
1135 .ndo_tx_timeout = hdd_tx_timeout,
1136 .ndo_get_stats = hdd_stats,
1137 .ndo_do_ioctl = hdd_ioctl,
1138 .ndo_set_mac_address = hdd_set_mac_address,
1139 };
1140#endif
1141
1142#endif
1143
1144void hdd_set_station_ops( struct net_device *pWlanDev )
1145{
1146#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1147 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
1148 pWlanDev->netdev_ops = &wlan_drv_ops;
1149#else
1150 pWlanDev->open = hdd_open;
1151 pWlanDev->stop = hdd_stop;
1152 pWlanDev->uninit = hdd_uninit;
1153 pWlanDev->hard_start_xmit = NULL;
1154 pWlanDev->tx_timeout = hdd_tx_timeout;
1155 pWlanDev->get_stats = hdd_stats;
1156 pWlanDev->do_ioctl = hdd_ioctl;
1157 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
1158 pWlanDev->set_mac_address = hdd_set_mac_address;
1159#endif
1160}
1161
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001162static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07001163{
1164 struct net_device *pWlanDev = NULL;
1165 hdd_adapter_t *pAdapter = NULL;
1166#ifdef CONFIG_CFG80211
1167 /*
1168 * cfg80211 initialization and registration....
1169 */
1170 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
1171
1172#else
1173 //Allocate the net_device and private data (station ctx)
1174 pWlanDev = alloc_etherdev_mq(sizeof( hdd_adapter_t ), NUM_TX_QUEUES);
1175
1176#endif
1177
1178 if(pWlanDev != NULL)
1179 {
1180
1181 //Save the pointer to the net_device in the HDD adapter
1182 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
1183
1184#ifndef CONFIG_CFG80211
1185 //Init the net_device structure
1186 ether_setup(pWlanDev);
1187#endif
1188
1189 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
1190
1191 pAdapter->dev = pWlanDev;
1192 pAdapter->pHddCtx = pHddCtx;
1193 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1194
1195 init_completion(&pAdapter->session_open_comp_var);
1196 init_completion(&pAdapter->session_close_comp_var);
1197 init_completion(&pAdapter->disconnect_comp_var);
1198 init_completion(&pAdapter->linkup_event_var);
1199 init_completion(&pAdapter->cancel_rem_on_chan_var);
1200 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001201#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1202 init_completion(&pAdapter->offchannel_tx_event);
1203#endif
1204#ifdef CONFIG_CFG80211
1205 init_completion(&pAdapter->tx_action_cnf_event);
1206#endif
1207 init_completion(&pHddCtx->mc_sus_event_var);
1208 init_completion(&pHddCtx->tx_sus_event_var);
1209
Jeff Johnson295189b2012-06-20 16:38:30 -07001210 pAdapter->isLinkUpSvcNeeded = FALSE;
1211 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1212 //Init the net_device structure
1213 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1214
1215 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1216 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1217 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1218 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1219
1220 hdd_set_station_ops( pAdapter->dev );
1221
1222 pWlanDev->destructor = free_netdev;
1223#ifdef CONFIG_CFG80211
1224 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1225 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1226 pAdapter->wdev.netdev = pWlanDev;
1227#endif
1228 /* set pWlanDev's parent to underlying device */
1229 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1230 }
1231
1232 return pAdapter;
1233}
1234
1235VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1236{
1237 struct net_device *pWlanDev = pAdapter->dev;
1238 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1239 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1240 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1241
1242 if( rtnl_lock_held )
1243 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001244 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001245 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1246 {
1247 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1248 return VOS_STATUS_E_FAILURE;
1249 }
1250 }
1251 if (register_netdevice(pWlanDev))
1252 {
1253 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1254 return VOS_STATUS_E_FAILURE;
1255 }
1256 }
1257 else
1258 {
1259 if(register_netdev(pWlanDev))
1260 {
1261 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1262 return VOS_STATUS_E_FAILURE;
1263 }
1264 }
1265 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1266
1267 return VOS_STATUS_SUCCESS;
1268}
1269
1270eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1271{
1272 if(pContext != NULL)
1273 {
1274 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1275
1276 /* need to make sure all of our scheduled work has completed.
1277 * This callback is called from MC thread context, so it is safe to
1278 * to call below flush workqueue API from here.
1279 */
1280 flush_scheduled_work();
1281 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1282 }
1283 return eHAL_STATUS_SUCCESS;
1284}
1285
1286VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1287{
1288 struct net_device *pWlanDev = pAdapter->dev;
1289 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1290 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1291 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1292 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1293 int rc = 0;
1294
1295 INIT_COMPLETION(pAdapter->session_open_comp_var);
1296 //Open a SME session for future operation
1297 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1298 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1299 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1300 {
1301 hddLog(VOS_TRACE_LEVEL_FATAL,
1302 "sme_OpenSession() failed with status code %08d [x%08lx]",
1303 halStatus, halStatus );
1304 status = VOS_STATUS_E_FAILURE;
1305 goto error_sme_open;
1306 }
1307
1308 //Block on a completion variable. Can't wait forever though.
1309 rc = wait_for_completion_interruptible_timeout(
1310 &pAdapter->session_open_comp_var,
1311 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1312 if (!rc)
1313 {
1314 hddLog(VOS_TRACE_LEVEL_FATAL,
1315 "Session is not opened within timeout period code %08d", rc );
1316 status = VOS_STATUS_E_FAILURE;
1317 goto error_sme_open;
1318 }
1319
1320 // Register wireless extensions
1321 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1322 {
1323 hddLog(VOS_TRACE_LEVEL_FATAL,
1324 "hdd_register_wext() failed with status code %08d [x%08lx]",
1325 halStatus, halStatus );
1326 status = VOS_STATUS_E_FAILURE;
1327 goto error_register_wext;
1328 }
1329 //Safe to register the hard_start_xmit function again
1330#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1331 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1332#else
1333 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1334#endif
1335
1336 //Set the Connection State to Not Connected
1337 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1338
1339 //Set the default operation channel
1340 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1341
1342 /* Make the default Auth Type as OPEN*/
1343 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1344
1345 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1346 {
1347 hddLog(VOS_TRACE_LEVEL_FATAL,
1348 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1349 status, status );
1350 goto error_init_txrx;
1351 }
1352
1353 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1354
1355 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1356 {
1357 hddLog(VOS_TRACE_LEVEL_FATAL,
1358 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1359 status, status );
1360 goto error_wmm_init;
1361 }
1362
1363 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1364
1365 return VOS_STATUS_SUCCESS;
1366
1367error_wmm_init:
1368 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1369 hdd_deinit_tx_rx(pAdapter);
1370error_init_txrx:
1371 hdd_UnregisterWext(pWlanDev);
1372error_register_wext:
1373 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1374 {
1375 INIT_COMPLETION(pAdapter->session_close_comp_var);
1376 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1377 pAdapter->sessionId,
1378 hdd_smeCloseSessionCallback, pAdapter ) )
1379 {
1380 //Block on a completion variable. Can't wait forever though.
1381 wait_for_completion_interruptible_timeout(
1382 &pAdapter->session_close_comp_var,
1383 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1384 }
1385}
1386error_sme_open:
1387 return status;
1388}
1389
Jeff Johnson295189b2012-06-20 16:38:30 -07001390#ifdef CONFIG_CFG80211
1391void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1392{
1393 hdd_cfg80211_state_t *cfgState;
1394
1395 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1396
1397 if( NULL != cfgState->buf )
1398 {
1399 int rc;
1400 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1401 rc = wait_for_completion_interruptible_timeout(
1402 &pAdapter->tx_action_cnf_event,
1403 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1404 if(!rc)
1405 {
1406 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1407 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1408 }
1409 }
1410 return;
1411}
1412#endif
1413
1414void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1415{
1416 ENTER();
1417 switch ( pAdapter->device_mode )
1418 {
1419 case WLAN_HDD_INFRA_STATION:
1420 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001421 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001422 {
1423 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1424 {
1425 hdd_deinit_tx_rx( pAdapter );
1426 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1427 }
1428
1429 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1430 {
1431 hdd_wmm_adapter_close( pAdapter );
1432 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1433 }
1434
1435#ifdef CONFIG_CFG80211
1436 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1437#endif
1438
1439 break;
1440 }
1441
1442 case WLAN_HDD_SOFTAP:
1443 case WLAN_HDD_P2P_GO:
1444#ifdef WLAN_SOFTAP_FEATURE
1445 {
1446#ifdef CONFIG_CFG80211
1447 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1448#endif
1449
1450 hdd_unregister_hostapd(pAdapter);
1451 hdd_set_conparam( 0 );
1452#ifdef CONFIG_CFG80211
1453 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
1454#endif
1455 break;
1456 }
1457
1458 case WLAN_HDD_MONITOR:
1459 {
1460#ifdef CONFIG_CFG80211
1461 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
1462#endif
1463 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1464 {
1465 hdd_deinit_tx_rx( pAdapter );
1466 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1467 }
1468#ifdef CONFIG_CFG80211
1469 if(NULL != pAdapterforTx)
1470 {
1471 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
1472 }
1473#endif
1474#endif //WLAN_SOFTAP_FEATURE
1475 break;
1476 }
1477
1478
1479 default:
1480 break;
1481 }
1482
1483 EXIT();
1484}
1485
1486void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
1487{
1488 struct net_device *pWlanDev = pAdapter->dev;
1489
1490 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
1491 if( rtnl_held )
1492 {
1493 unregister_netdevice(pWlanDev);
1494 }
1495 else
1496 {
1497 unregister_netdev(pWlanDev);
1498 }
1499 // note that the pAdapter is no longer valid at this point
1500 // since the memory has been reclaimed
1501 }
1502
1503}
1504
1505VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
1506{
1507 VOS_STATUS status = VOS_STATUS_SUCCESS;
1508
1509 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
1510 {
1511 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1512 }
1513
1514 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
1515 {
1516 sme_StartAutoBmpsTimer(pHddCtx->hHal);
1517 }
1518
1519 if (pHddCtx->cfg_ini->fIsImpsEnabled)
1520 {
1521 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1522 }
1523
1524 return status;
1525}
1526
1527VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
1528{
1529 hdd_adapter_t *pAdapter = NULL;
1530 eHalStatus halStatus;
1531 VOS_STATUS status = VOS_STATUS_E_INVAL;
1532 v_BOOL_t disableBmps = FALSE;
1533 v_BOOL_t disableImps = FALSE;
1534
1535 switch(session_type)
1536 {
1537 case WLAN_HDD_INFRA_STATION:
1538 case WLAN_HDD_SOFTAP:
1539#ifdef WLAN_FEATURE_P2P
1540 case WLAN_HDD_P2P_CLIENT:
1541 case WLAN_HDD_P2P_GO:
1542#endif
1543 //Exit BMPS -> Is Sta/P2P Client is already connected
1544 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
1545 if((NULL != pAdapter)&&
1546 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1547 {
1548 disableBmps = TRUE;
1549 }
1550
1551 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
1552 if((NULL != pAdapter)&&
1553 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1554 {
1555 disableBmps = TRUE;
1556 }
1557
1558 //Exit both Bmps and Imps incase of Go/SAP Mode
1559 if((WLAN_HDD_SOFTAP == session_type) ||
1560 (WLAN_HDD_P2P_GO == session_type))
1561 {
1562 disableBmps = TRUE;
1563 disableImps = TRUE;
1564 }
1565
1566 if(TRUE == disableImps)
1567 {
1568 if (pHddCtx->cfg_ini->fIsImpsEnabled)
1569 {
1570 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
1571 }
1572 }
1573
1574 if(TRUE == disableBmps)
1575 {
1576 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
1577 {
1578 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
1579
1580 if(eHAL_STATUS_SUCCESS != halStatus)
1581 {
1582 status = VOS_STATUS_E_FAILURE;
1583 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
1584 VOS_ASSERT(0);
1585 return status;
1586 }
1587 }
1588
1589 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
1590 {
1591 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
1592
1593 if(eHAL_STATUS_SUCCESS != halStatus)
1594 {
1595 status = VOS_STATUS_E_FAILURE;
1596 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
1597 VOS_ASSERT(0);
1598 return status;
1599 }
1600 }
1601 }
1602
1603 if((TRUE == disableBmps) ||
1604 (TRUE == disableImps))
1605 {
1606 /* Now, get the chip into Full Power now */
1607 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
1608 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
1609 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
1610
1611 if(halStatus != eHAL_STATUS_SUCCESS)
1612 {
1613 if(halStatus == eHAL_STATUS_PMC_PENDING)
1614 {
1615 //Block on a completion variable. Can't wait forever though
1616 wait_for_completion_interruptible_timeout(
1617 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
1618 }
1619 else
1620 {
1621 status = VOS_STATUS_E_FAILURE;
1622 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
1623 VOS_ASSERT(0);
1624 return status;
1625 }
1626 }
1627
1628 status = VOS_STATUS_SUCCESS;
1629 }
1630
1631 break;
1632 }
1633 return status;
1634}
1635
1636hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001637 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07001638 tANI_U8 rtnl_held )
1639{
1640 hdd_adapter_t *pAdapter = NULL;
1641 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
1642 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1643 VOS_STATUS exitbmpsStatus;
1644
1645 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
1646
1647 //Disable BMPS incase of Concurrency
1648 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
1649
1650 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
1651 {
1652 //Fail to Exit BMPS
1653 VOS_ASSERT(0);
1654 return NULL;
1655 }
1656
1657 switch(session_type)
1658 {
1659 case WLAN_HDD_INFRA_STATION:
1660#ifdef WLAN_FEATURE_P2P
1661 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001662 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001663#endif
1664 {
1665 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
1666
1667 if( NULL == pAdapter )
1668 return NULL;
1669
1670#ifdef CONFIG_CFG80211
Jeff Johnsone7245742012-09-05 17:12:55 -07001671 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
1672 NL80211_IFTYPE_P2P_CLIENT:
1673 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07001674#endif
1675
Jeff Johnson295189b2012-06-20 16:38:30 -07001676 pAdapter->device_mode = session_type;
1677
1678 status = hdd_init_station_mode( pAdapter );
1679 if( VOS_STATUS_SUCCESS != status )
1680 goto err_free_netdev;
1681
1682 status = hdd_register_interface( pAdapter, rtnl_held );
1683 if( VOS_STATUS_SUCCESS != status )
1684 {
1685 hdd_deinit_adapter(pHddCtx, pAdapter);
1686 goto err_free_netdev;
1687 }
1688 //Stop the Interface TX queue.
1689 netif_tx_disable(pAdapter->dev);
1690 //netif_tx_disable(pWlanDev);
1691 netif_carrier_off(pAdapter->dev);
1692
1693 break;
1694 }
1695
1696#ifdef WLAN_FEATURE_P2P
1697 case WLAN_HDD_P2P_GO:
1698#endif
1699 case WLAN_HDD_SOFTAP:
1700 {
1701 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
1702 if( NULL == pAdapter )
1703 return NULL;
1704
1705#ifdef CONFIG_CFG80211
1706 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
1707 NL80211_IFTYPE_AP:
1708 NL80211_IFTYPE_P2P_GO;
1709#endif
1710 pAdapter->device_mode = session_type;
1711
1712 status = hdd_init_ap_mode(pAdapter);
1713 if( VOS_STATUS_SUCCESS != status )
1714 goto err_free_netdev;
1715
1716 status = hdd_register_hostapd( pAdapter, rtnl_held );
1717 if( VOS_STATUS_SUCCESS != status )
1718 {
1719 hdd_deinit_adapter(pHddCtx, pAdapter);
1720 goto err_free_netdev;
1721 }
1722
1723 netif_tx_disable(pAdapter->dev);
1724 netif_carrier_off(pAdapter->dev);
1725
1726 hdd_set_conparam( 1 );
1727 break;
1728 }
1729 case WLAN_HDD_MONITOR:
1730 {
1731#ifdef CONFIG_CFG80211
1732 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
1733 if( NULL == pAdapter )
1734 return NULL;
1735
1736 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
1737 pAdapter->device_mode = session_type;
1738 status = hdd_register_interface( pAdapter, rtnl_held );
1739#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
1740 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
1741#else
1742 pAdapter->dev->open = hdd_mon_open;
1743 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
1744#endif
1745 hdd_init_tx_rx( pAdapter );
1746 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1747 //Set adapter to be used for data tx. It will use either GO or softap.
1748 pAdapter->sessionCtx.monitor.pAdapterForTx =
1749 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
1750#ifdef WLAN_FEATURE_P2P
1751 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
1752 {
1753 pAdapter->sessionCtx.monitor.pAdapterForTx =
1754 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
1755 }
1756#endif
1757 /* This workqueue will be used to transmit management packet over
1758 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07001759 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
1760 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
1761 return NULL;
1762 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07001763
Jeff Johnson295189b2012-06-20 16:38:30 -07001764 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
1765 hdd_mon_tx_work_queue);
1766#endif
1767 }
1768 break;
1769#ifdef ANI_MANF_DIAG
1770 case WLAN_HDD_FTM:
1771 {
1772 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
1773
1774 if( NULL == pAdapter )
1775 return NULL;
1776 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
1777 * message while loading driver in FTM mode. */
1778 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
1779 pAdapter->device_mode = session_type;
1780 status = hdd_register_interface( pAdapter, rtnl_held );
1781 }
1782 break;
1783#endif
1784 default:
1785 {
1786 VOS_ASSERT(0);
1787 return NULL;
1788 }
1789 }
1790
1791
1792 if( VOS_STATUS_SUCCESS == status )
1793 {
1794 //Add it to the hdd's session list.
1795 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
1796 if( NULL == pHddAdapterNode )
1797 {
1798 status = VOS_STATUS_E_NOMEM;
1799 }
1800 else
1801 {
1802 pHddAdapterNode->pAdapter = pAdapter;
1803 status = hdd_add_adapter_back ( pHddCtx,
1804 pHddAdapterNode );
1805 }
1806 }
1807
1808 if( VOS_STATUS_SUCCESS != status )
1809 {
1810 if( NULL != pAdapter )
1811 {
1812 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
1813 pAdapter = NULL;
1814 }
1815 if( NULL != pHddAdapterNode )
1816 {
1817 vos_mem_free( pHddAdapterNode );
1818 }
1819
1820 goto resume_bmps;
1821 }
1822
1823 if(VOS_STATUS_SUCCESS == status)
1824 {
1825 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
1826
1827#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1828 /* If there are concurrent session enable SW frame translation
1829 * for all registered STA
1830 * This is not required in case of PRIMA as HW frame translation
1831 * is disabled in PRIMA*/
1832 if (vos_concurrent_sessions_running())
1833 {
1834 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, TRUE);
1835 }
1836#endif
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07001837 //Initialize the WoWL service
1838 if(!hdd_init_wowl(pAdapter))
1839 {
1840 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
1841 goto err_free_netdev;
1842 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001843 }
Jeff Johnson295189b2012-06-20 16:38:30 -07001844 return pAdapter;
1845
1846err_free_netdev:
1847 free_netdev(pAdapter->dev);
1848 wlan_hdd_release_intf_addr( pHddCtx,
1849 pAdapter->macAddressCurrent.bytes );
1850
1851resume_bmps:
1852 //If bmps disabled enable it
1853 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
1854 {
1855 hdd_enable_bmps_imps(pHddCtx);
1856 }
1857 return NULL;
1858}
1859
1860VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
1861 tANI_U8 rtnl_held )
1862{
1863 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
1864 VOS_STATUS status;
1865
1866 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
1867 if( VOS_STATUS_SUCCESS != status )
1868 return status;
1869
1870 while ( pCurrent->pAdapter != pAdapter )
1871 {
1872 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
1873 if( VOS_STATUS_SUCCESS != status )
1874 break;
1875
1876 pCurrent = pNext;
1877 }
1878 pAdapterNode = pCurrent;
1879 if( VOS_STATUS_SUCCESS == status )
1880 {
1881 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
1882 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
1883 hdd_remove_adapter( pHddCtx, pAdapterNode );
1884 vos_mem_free( pAdapterNode );
1885
1886#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
1887 /* If there is no concurrent session disable SW frame translation
1888 * for all registered STA */
1889 /* This is not required in case of PRIMA as HW frame translation
1890 * is disabled in PRIMA*/
1891 if (!vos_concurrent_sessions_running())
1892 {
1893 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, FALSE);
1894 }
1895#endif
1896
1897 /* If there is a single session of STA/P2P client, re-enable BMPS */
1898 if ((!vos_concurrent_sessions_running()) &&
1899 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
1900 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
1901 {
1902 hdd_enable_bmps_imps(pHddCtx);
1903 }
1904
1905 return VOS_STATUS_SUCCESS;
1906 }
1907
1908 return VOS_STATUS_E_FAILURE;
1909}
1910
1911VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
1912{
1913 hdd_adapter_list_node_t *pHddAdapterNode;
1914 VOS_STATUS status;
1915
1916 ENTER();
1917
1918 do
1919 {
1920 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
1921 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
1922 {
1923 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
1924 vos_mem_free( pHddAdapterNode );
1925 }
1926 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
1927
1928 EXIT();
1929
1930 return VOS_STATUS_SUCCESS;
1931}
1932
1933void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
1934{
1935 v_U8_t addIE[1] = {0};
1936
1937 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1938 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
1939 eANI_BOOLEAN_FALSE) )
1940 {
1941 hddLog(LOGE,
1942 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
1943 }
1944
1945 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1946 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
1947 eANI_BOOLEAN_FALSE) )
1948 {
1949 hddLog(LOGE,
1950 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
1951 }
1952
1953 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
1954 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
1955 eANI_BOOLEAN_FALSE) )
1956 {
1957 hddLog(LOGE,
1958 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
1959 }
1960}
1961
1962VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1963{
1964 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1965 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
1966 union iwreq_data wrqu;
1967
1968 ENTER();
1969
1970 switch(pAdapter->device_mode)
1971 {
1972 case WLAN_HDD_INFRA_STATION:
1973 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07001974 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07001975 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
1976 {
1977 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
1978 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
1979 pAdapter->sessionId,
1980 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
1981 else
1982 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
1983 pAdapter->sessionId,
1984 eCSR_DISCONNECT_REASON_UNSPECIFIED);
1985 //success implies disconnect command got queued up successfully
1986 if(halStatus == eHAL_STATUS_SUCCESS)
1987 {
1988 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
1989 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
1990 }
1991 memset(&wrqu, '\0', sizeof(wrqu));
1992 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
1993 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
1994 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
1995 }
1996 else
1997 {
1998 hdd_abort_mac_scan(pHddCtx);
1999 }
2000
2001 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2002 {
2003 INIT_COMPLETION(pAdapter->session_close_comp_var);
2004 if (eHAL_STATUS_SUCCESS ==
2005 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2006 hdd_smeCloseSessionCallback, pAdapter))
2007 {
2008 //Block on a completion variable. Can't wait forever though.
2009 wait_for_completion_interruptible_timeout(
2010 &pAdapter->session_close_comp_var,
2011 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2012 }
2013 }
2014
2015 break;
2016
2017 case WLAN_HDD_SOFTAP:
2018 case WLAN_HDD_P2P_GO:
2019 //Any softap specific cleanup here...
2020 mutex_lock(&pHddCtx->sap_lock);
2021 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2022 {
2023 VOS_STATUS status;
2024 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2025
2026 //Stop Bss.
2027 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2028 if (VOS_IS_STATUS_SUCCESS(status))
2029 {
2030 hdd_hostapd_state_t *pHostapdState =
2031 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2032
2033 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2034
2035 if (!VOS_IS_STATUS_SUCCESS(status))
2036 {
2037 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002038 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002039 }
2040 }
2041 else
2042 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002043 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002044 }
2045 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2046
2047 if (eHAL_STATUS_FAILURE ==
2048 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2049 0, NULL, eANI_BOOLEAN_FALSE))
2050 {
2051 hddLog(LOGE,
2052 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002053 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002054 }
2055
2056 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2057 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2058 eANI_BOOLEAN_FALSE) )
2059 {
2060 hddLog(LOGE,
2061 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2062 }
2063
2064 // Reset WNI_CFG_PROBE_RSP Flags
2065 wlan_hdd_reset_prob_rspies(pAdapter);
2066 kfree(pAdapter->sessionCtx.ap.beacon);
2067 pAdapter->sessionCtx.ap.beacon = NULL;
2068 }
2069 mutex_unlock(&pHddCtx->sap_lock);
2070 break;
2071 case WLAN_HDD_MONITOR:
2072 break;
2073 default:
2074 break;
2075 }
2076
2077 EXIT();
2078 return VOS_STATUS_SUCCESS;
2079}
2080
2081VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2082{
2083 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2084 VOS_STATUS status;
2085 hdd_adapter_t *pAdapter;
2086
2087 ENTER();
2088
2089 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2090
2091 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2092 {
2093 pAdapter = pAdapterNode->pAdapter;
2094 netif_tx_disable(pAdapter->dev);
2095 netif_carrier_off(pAdapter->dev);
2096
2097 hdd_stop_adapter( pHddCtx, pAdapter );
2098
2099 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2100 pAdapterNode = pNext;
2101 }
2102
2103 EXIT();
2104
2105 return VOS_STATUS_SUCCESS;
2106}
2107
2108VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2109{
2110 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2111 VOS_STATUS status;
2112 hdd_adapter_t *pAdapter;
2113
2114 ENTER();
2115
2116 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2117
2118 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2119 {
2120 pAdapter = pAdapterNode->pAdapter;
2121 netif_tx_disable(pAdapter->dev);
2122 netif_carrier_off(pAdapter->dev);
2123
2124 //Record whether STA is associated
2125 pAdapter->sessionCtx.station.bSendDisconnect =
2126 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2127 VOS_TRUE : VOS_FALSE;
2128
2129 hdd_deinit_tx_rx(pAdapter);
2130 hdd_wmm_adapter_close(pAdapter);
2131
2132 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2133 pAdapterNode = pNext;
2134 }
2135
2136 EXIT();
2137
2138 return VOS_STATUS_SUCCESS;
2139}
2140
2141VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2142{
2143 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2144 VOS_STATUS status;
2145 hdd_adapter_t *pAdapter;
2146 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2147
2148 ENTER();
2149
2150 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2151
2152 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2153 {
2154 pAdapter = pAdapterNode->pAdapter;
2155
2156 switch(pAdapter->device_mode)
2157 {
2158 case WLAN_HDD_INFRA_STATION:
2159 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002160 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002161 hdd_init_station_mode(pAdapter);
2162 /* Open the gates for HDD to receive Wext commands */
2163 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002164 pHddCtx->scan_info.mScanPending = FALSE;
2165 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002166
2167 //Trigger the initial scan
2168 hdd_wlan_initial_scan(pAdapter);
2169
2170 //Indicate disconnect event to supplicant if associated previously
2171 if(pAdapter->sessionCtx.station.bSendDisconnect)
2172 {
2173 union iwreq_data wrqu;
2174 memset(&wrqu, '\0', sizeof(wrqu));
2175 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2176 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2177 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2178 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2179
2180#ifdef CONFIG_CFG80211
2181 /* indicate disconnected event to nl80211 */
2182 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2183 NULL, 0, GFP_KERNEL);
2184#endif
2185 }
2186 break;
2187
2188 case WLAN_HDD_SOFTAP:
2189 /* softAP can handle SSR */
2190 break;
2191
2192 case WLAN_HDD_P2P_GO:
2193#ifdef CONFIG_CFG80211
2194 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2195 __func__);
2196 /* event supplicant to restart */
2197 cfg80211_del_sta(pAdapter->dev,
2198 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
2199#endif
2200 break;
2201
2202 case WLAN_HDD_MONITOR:
2203 /* monitor interface start */
2204 break;
2205 default:
2206 break;
2207 }
2208
2209 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2210 pAdapterNode = pNext;
2211 }
2212
2213 EXIT();
2214
2215 return VOS_STATUS_SUCCESS;
2216}
2217
2218VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2219{
2220 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2221 hdd_adapter_t *pAdapter;
2222 VOS_STATUS status;
2223 v_U32_t roamId;
2224
2225 ENTER();
2226
2227 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2228
2229 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2230 {
2231 pAdapter = pAdapterNode->pAdapter;
2232
2233 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2234 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2235 {
2236 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2237 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2238
2239 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2240 init_completion(&pAdapter->disconnect_comp_var);
2241 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2242 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2243
2244 wait_for_completion_interruptible_timeout(
2245 &pAdapter->disconnect_comp_var,
2246 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2247
2248 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2249 pHddCtx->isAmpAllowed = VOS_FALSE;
2250 sme_RoamConnect(pHddCtx->hHal,
2251 pAdapter->sessionId, &(pWextState->roamProfile),
2252 &roamId);
2253 }
2254
2255 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2256 pAdapterNode = pNext;
2257 }
2258
2259 EXIT();
2260
2261 return VOS_STATUS_SUCCESS;
2262}
2263
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002264bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002265{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002266 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002267}
2268
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002269/* Once SSR is disabled then it cannot be set. */
2270void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002271{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002272 if (HDD_SSR_DISABLED == isSsrRequired)
2273 return;
2274
Jeff Johnson295189b2012-06-20 16:38:30 -07002275 isSsrRequired = value;
2276}
2277
2278VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2279 hdd_adapter_list_node_t** ppAdapterNode)
2280{
2281 VOS_STATUS status;
2282 spin_lock(&pHddCtx->hddAdapters.lock);
2283 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2284 (hdd_list_node_t**) ppAdapterNode );
2285 spin_unlock(&pHddCtx->hddAdapters.lock);
2286 return status;
2287}
2288
2289VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2290 hdd_adapter_list_node_t* pAdapterNode,
2291 hdd_adapter_list_node_t** pNextAdapterNode)
2292{
2293 VOS_STATUS status;
2294 spin_lock(&pHddCtx->hddAdapters.lock);
2295 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2296 (hdd_list_node_t*) pAdapterNode,
2297 (hdd_list_node_t**)pNextAdapterNode );
2298
2299 spin_unlock(&pHddCtx->hddAdapters.lock);
2300 return status;
2301}
2302
2303VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2304 hdd_adapter_list_node_t* pAdapterNode)
2305{
2306 VOS_STATUS status;
2307 spin_lock(&pHddCtx->hddAdapters.lock);
2308 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2309 &pAdapterNode->node );
2310 spin_unlock(&pHddCtx->hddAdapters.lock);
2311 return status;
2312}
2313
2314VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2315 hdd_adapter_list_node_t** ppAdapterNode)
2316{
2317 VOS_STATUS status;
2318 spin_lock(&pHddCtx->hddAdapters.lock);
2319 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2320 (hdd_list_node_t**) ppAdapterNode );
2321 spin_unlock(&pHddCtx->hddAdapters.lock);
2322 return status;
2323}
2324
2325VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2326 hdd_adapter_list_node_t* pAdapterNode)
2327{
2328 VOS_STATUS status;
2329 spin_lock(&pHddCtx->hddAdapters.lock);
2330 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2331 (hdd_list_node_t*) pAdapterNode );
2332 spin_unlock(&pHddCtx->hddAdapters.lock);
2333 return status;
2334}
2335
2336VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2337 hdd_adapter_list_node_t* pAdapterNode)
2338{
2339 VOS_STATUS status;
2340 spin_lock(&pHddCtx->hddAdapters.lock);
2341 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2342 (hdd_list_node_t*) pAdapterNode );
2343 spin_unlock(&pHddCtx->hddAdapters.lock);
2344 return status;
2345}
2346
2347hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2348 tSirMacAddr macAddr )
2349{
2350 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2351 hdd_adapter_t *pAdapter;
2352 VOS_STATUS status;
2353
2354 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2355
2356 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2357 {
2358 pAdapter = pAdapterNode->pAdapter;
2359
2360 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2361 macAddr, sizeof(tSirMacAddr) ) )
2362 {
2363 return pAdapter;
2364 }
2365 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2366 pAdapterNode = pNext;
2367 }
2368
2369 return NULL;
2370
2371}
2372
2373hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2374{
2375 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2376 hdd_adapter_t *pAdapter;
2377 VOS_STATUS status;
2378
2379 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2380
2381 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2382 {
2383 pAdapter = pAdapterNode->pAdapter;
2384
2385 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2386 IFNAMSIZ ) )
2387 {
2388 return pAdapter;
2389 }
2390 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2391 pAdapterNode = pNext;
2392 }
2393
2394 return NULL;
2395
2396}
2397
2398hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
2399{
2400 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2401 hdd_adapter_t *pAdapter;
2402 VOS_STATUS status;
2403
2404 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2405
2406 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2407 {
2408 pAdapter = pAdapterNode->pAdapter;
2409
2410 if( pAdapter && (mode == pAdapter->device_mode) )
2411 {
2412 return pAdapter;
2413 }
2414 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2415 pAdapterNode = pNext;
2416 }
2417
2418 return NULL;
2419
2420}
2421
2422//Remove this function later
2423hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
2424{
2425 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2426 hdd_adapter_t *pAdapter;
2427 VOS_STATUS status;
2428
2429 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2430
2431 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2432 {
2433 pAdapter = pAdapterNode->pAdapter;
2434
2435 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
2436 {
2437 return pAdapter;
2438 }
2439
2440 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2441 pAdapterNode = pNext;
2442 }
2443
2444 return NULL;
2445
2446}
2447
2448#ifdef CONFIG_CFG80211
2449/**---------------------------------------------------------------------------
2450
2451 \brief hdd_set_monitor_tx_adapter() -
2452
2453 This API initializes the adapter to be used while transmitting on monitor
2454 adapter.
2455
2456 \param - pHddCtx - Pointer to the HDD context.
2457 pAdapter - Adapter that will used for TX. This can be NULL.
2458 \return - None.
2459 --------------------------------------------------------------------------*/
2460void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2461{
2462 hdd_adapter_t *pMonAdapter;
2463
2464 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
2465
2466 if( NULL != pMonAdapter )
2467 {
2468 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
2469 }
2470}
2471#endif
2472/**---------------------------------------------------------------------------
2473
2474 \brief hdd_select_queue() -
2475
2476 This API returns the operating channel of the requested device mode
2477
2478 \param - pHddCtx - Pointer to the HDD context.
2479 - mode - Device mode for which operating channel is required
2480 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
2481 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
2482 \return - channel number. "0" id the requested device is not found OR it is not connected.
2483 --------------------------------------------------------------------------*/
2484v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
2485{
2486 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2487 VOS_STATUS status;
2488 hdd_adapter_t *pAdapter;
2489 v_U8_t operatingChannel = 0;
2490
2491 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2492
2493 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2494 {
2495 pAdapter = pAdapterNode->pAdapter;
2496
2497 if( mode == pAdapter->device_mode )
2498 {
2499 switch(pAdapter->device_mode)
2500 {
2501 case WLAN_HDD_INFRA_STATION:
2502 case WLAN_HDD_P2P_CLIENT:
2503 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2504 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
2505 break;
2506 case WLAN_HDD_SOFTAP:
2507 case WLAN_HDD_P2P_GO:
2508 /*softap connection info */
2509 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2510 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
2511 break;
2512 default:
2513 break;
2514 }
2515
2516 break; //Found the device of interest. break the loop
2517 }
2518
2519 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2520 pAdapterNode = pNext;
2521 }
2522 return operatingChannel;
2523}
2524
2525#ifdef WLAN_FEATURE_PACKET_FILTERING
2526/**---------------------------------------------------------------------------
2527
2528 \brief hdd_set_multicast_list() -
2529
2530 This used to set the multicast address list.
2531
2532 \param - dev - Pointer to the WLAN device.
2533 - skb - Pointer to OS packet (sk_buff).
2534 \return - success/fail
2535
2536 --------------------------------------------------------------------------*/
2537static void hdd_set_multicast_list(struct net_device *dev)
2538{
2539 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
2540 hdd_context_t *pHddCtx;
2541 int mc_count;
2542 int i = 0;
2543 struct netdev_hw_addr *ha;
2544 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
2545 if (NULL == pHddCtx)
2546 {
2547 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002548 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002549 return;
2550 }
2551
2552 if (dev->flags & IFF_ALLMULTI)
2553 {
2554 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002555 "%s: allow all multicast frames", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002556 pHddCtx->mc_addr_list.mc_cnt = 0;
2557 }
2558 else
2559 {
2560 mc_count = netdev_mc_count(dev);
2561 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002562 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07002563 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
2564 {
2565 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002566 "%s: No free filter available; allow all multicast frames", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002567 pHddCtx->mc_addr_list.mc_cnt = 0;
2568 return;
2569 }
2570
2571 pHddCtx->mc_addr_list.mc_cnt = mc_count;
2572
2573 netdev_for_each_mc_addr(ha, dev) {
2574 if (i == mc_count)
2575 break;
2576 memset(&(pHddCtx->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
2577 memcpy(&(pHddCtx->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
2578 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = %02x:%02x:%02x:%02x:%02x:%02x",
2579 __func__, i,
2580 pHddCtx->mc_addr_list.addr[i][0], pHddCtx->mc_addr_list.addr[i][1],
2581 pHddCtx->mc_addr_list.addr[i][2], pHddCtx->mc_addr_list.addr[i][3],
2582 pHddCtx->mc_addr_list.addr[i][4], pHddCtx->mc_addr_list.addr[i][5]);
2583 i++;
2584 }
2585 }
2586 return;
2587}
2588#endif
2589
2590/**---------------------------------------------------------------------------
2591
2592 \brief hdd_select_queue() -
2593
2594 This function is registered with the Linux OS for network
2595 core to decide which queue to use first.
2596
2597 \param - dev - Pointer to the WLAN device.
2598 - skb - Pointer to OS packet (sk_buff).
2599 \return - ac, Queue Index/access category corresponding to UP in IP header
2600
2601 --------------------------------------------------------------------------*/
2602v_U16_t hdd_select_queue(struct net_device *dev,
2603 struct sk_buff *skb)
2604{
2605 return hdd_wmm_select_queue(dev, skb);
2606}
2607
2608
2609/**---------------------------------------------------------------------------
2610
2611 \brief hdd_wlan_initial_scan() -
2612
2613 This function triggers the initial scan
2614
2615 \param - pAdapter - Pointer to the HDD adapter.
2616
2617 --------------------------------------------------------------------------*/
2618void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
2619{
2620 tCsrScanRequest scanReq;
2621 tCsrChannelInfo channelInfo;
2622 eHalStatus halStatus;
2623 unsigned long scanId;
2624 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2625
2626 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
2627 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
2628 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
2629
2630 if(sme_Is11dSupported(pHddCtx->hHal))
2631 {
2632 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
2633 if ( HAL_STATUS_SUCCESS( halStatus ) )
2634 {
2635 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
2636 if( !scanReq.ChannelInfo.ChannelList )
2637 {
2638 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
2639 vos_mem_free(channelInfo.ChannelList);
2640 return;
2641 }
2642 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
2643 channelInfo.numOfChannels);
2644 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
2645 vos_mem_free(channelInfo.ChannelList);
2646 }
2647
2648 scanReq.scanType = eSIR_PASSIVE_SCAN;
2649 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
2650 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
2651 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
2652 }
2653 else
2654 {
2655 scanReq.scanType = eSIR_ACTIVE_SCAN;
2656 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
2657 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
2658 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
2659 }
2660
2661 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
2662 if ( !HAL_STATUS_SUCCESS( halStatus ) )
2663 {
2664 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
2665 __func__, halStatus );
2666 }
2667
2668 if(sme_Is11dSupported(pHddCtx->hHal))
2669 vos_mem_free(scanReq.ChannelInfo.ChannelList);
2670}
2671
2672struct fullPowerContext
2673{
2674 struct completion completion;
2675 unsigned int magic;
2676};
2677#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
2678
2679/**---------------------------------------------------------------------------
2680
2681 \brief hdd_full_power_callback() - HDD full power callback function
2682
2683 This is the function invoked by SME to inform the result of a full power
2684 request issued by HDD
2685
2686 \param - callbackcontext - Pointer to cookie
2687 \param - status - result of request
2688
2689 \return - None
2690
2691 --------------------------------------------------------------------------*/
2692static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
2693{
2694 struct fullPowerContext *pContext = callbackContext;
2695
2696 hddLog(VOS_TRACE_LEVEL_INFO,
2697 "%s: context = %p, status = %d", pContext, status);
2698
2699 if (NULL == callbackContext)
2700 {
2701 hddLog(VOS_TRACE_LEVEL_ERROR,
2702 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002703 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07002704 return;
2705 }
2706
2707 /* there is a race condition that exists between this callback function
2708 and the caller since the caller could time out either before or
2709 while this code is executing. we'll assume the timeout hasn't
2710 occurred, but we'll verify that right before we save our work */
2711
2712 if (POWER_CONTEXT_MAGIC != pContext->magic)
2713 {
2714 /* the caller presumably timed out so there is nothing we can do */
2715 hddLog(VOS_TRACE_LEVEL_WARN,
2716 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002717 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07002718 return;
2719 }
2720
2721 /* the race is on. caller could have timed out immediately after
2722 we verified the magic, but if so, caller will wait a short time
2723 for us to notify the caller, so the context will stay valid */
2724 complete(&pContext->completion);
2725}
2726
2727/**---------------------------------------------------------------------------
2728
2729 \brief hdd_wlan_exit() - HDD WLAN exit function
2730
2731 This is the driver exit point (invoked during rmmod)
2732
2733 \param - pHddCtx - Pointer to the HDD Context
2734
2735 \return - None
2736
2737 --------------------------------------------------------------------------*/
2738void hdd_wlan_exit(hdd_context_t *pHddCtx)
2739{
2740 eHalStatus halStatus;
2741 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
2742 VOS_STATUS vosStatus;
2743#ifdef ANI_BUS_TYPE_SDIO
2744 struct sdio_func *sdio_func_dev = NULL;
2745#endif // ANI_BUS_TYPE_SDIO
2746#ifdef CONFIG_CFG80211
2747 struct wiphy *wiphy = pHddCtx->wiphy;
2748#endif
2749#ifdef FEATURE_WLAN_INTEGRATED_SOC
2750 hdd_adapter_t* pAdapter;
2751#endif
2752 struct fullPowerContext powerContext;
2753 long lrc;
2754
2755 ENTER();
2756
Ng Chilam1322ea32012-12-27 17:33:08 -08002757#ifdef ANI_MANF_DIAG
2758 if (VOS_FTM_MODE != hdd_get_conparam())
2759#endif /* ANI_MANF_DIAG */
2760 {
2761 // Unloading, restart logic is no more required.
2762 wlan_hdd_restart_deinit(pHddCtx);
2763 }
Jeff Johnsone7245742012-09-05 17:12:55 -07002764
Jeff Johnson295189b2012-06-20 16:38:30 -07002765#ifdef CONFIG_CFG80211
2766#ifdef WLAN_SOFTAP_FEATURE
2767 if (VOS_STA_SAP_MODE != hdd_get_conparam())
2768#endif
2769 {
2770#ifdef ANI_MANF_DIAG
2771 if (VOS_FTM_MODE != hdd_get_conparam())
2772#endif /* ANI_MANF_DIAG */
2773 {
2774 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
2775 WLAN_HDD_INFRA_STATION);
2776 if (pAdapter == NULL)
2777 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2778
2779 if (pAdapter != NULL)
2780 {
2781 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
2782 hdd_UnregisterWext(pAdapter->dev);
2783 }
2784 }
2785 }
2786#endif
2787
2788#ifdef ANI_MANF_DIAG
2789 if (VOS_FTM_MODE == hdd_get_conparam())
2790 {
2791 wlan_hdd_ftm_close(pHddCtx);
2792 goto free_hdd_ctx;
2793 }
2794#endif
2795 //Stop the Interface TX queue.
2796 //netif_tx_disable(pWlanDev);
2797 //netif_carrier_off(pWlanDev);
2798
Jeff Johnson295189b2012-06-20 16:38:30 -07002799#ifdef FEATURE_WLAN_INTEGRATED_SOC
2800#ifdef WLAN_SOFTAP_FEATURE
2801 if (VOS_STA_SAP_MODE == hdd_get_conparam())
2802 {
2803 pAdapter = hdd_get_adapter(pHddCtx,
2804 WLAN_HDD_SOFTAP);
2805 }
2806 else
2807 {
2808#endif
2809#ifdef ANI_MANF_DIAG
2810 if (VOS_FTM_MODE != hdd_get_conparam())
2811#endif /* ANI_MANF_DIAG */
2812 {
2813 pAdapter = hdd_get_adapter(pHddCtx,
2814 WLAN_HDD_INFRA_STATION);
2815 }
2816#ifdef WLAN_SOFTAP_FEATURE
2817 }
2818#endif
2819 /* DeRegister with platform driver as client for Suspend/Resume */
2820 vosStatus = hddDeregisterPmOps(pHddCtx);
2821 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2822 {
2823 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
2824 VOS_ASSERT(0);
2825 }
2826
2827 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
2828 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
2829 {
2830 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
2831 }
2832#endif //FEATURE_WLAN_INTEGRATED_SOC
2833
Chilam NG571c65a2013-01-19 12:27:36 +05302834#ifdef FEATURE_WLAN_TDLS
2835 wlan_hdd_tdls_exit();
2836#endif
2837
Jeff Johnson295189b2012-06-20 16:38:30 -07002838 // Cancel any outstanding scan requests. We are about to close all
2839 // of our adapters, but an adapter structure is what SME passes back
2840 // to our callback function. Hence if there are any outstanding scan
2841 // requests then there is a race condition between when the adapter
2842 // is closed and when the callback is invoked. We try to resolve that
2843 // race condition here by canceling any outstanding scans before we
2844 // close the adapters.
2845 // Note that the scans may be cancelled in an asynchronous manner, so
2846 // ideally there needs to be some kind of synchronization. Rather than
2847 // introduce a new synchronization here, we will utilize the fact that
2848 // we are about to Request Full Power, and since that is synchronized,
2849 // the expectation is that by the time Request Full Power has completed,
2850 // all scans will be cancelled.
2851 hdd_abort_mac_scan( pHddCtx );
2852
2853 //Disable IMPS/BMPS as we do not want the device to enter any power
2854 //save mode during shutdown
2855 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2856 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2857 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
2858
2859 //Ensure that device is in full power as we will touch H/W during vos_Stop
2860 init_completion(&powerContext.completion);
2861 powerContext.magic = POWER_CONTEXT_MAGIC;
2862
2863 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
2864 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
2865
2866 if (eHAL_STATUS_SUCCESS != halStatus)
2867 {
2868 if (eHAL_STATUS_PMC_PENDING == halStatus)
2869 {
2870 /* request was sent -- wait for the response */
2871 lrc = wait_for_completion_interruptible_timeout(
2872 &powerContext.completion,
2873 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
2874 /* either we have a response or we timed out
2875 either way, first invalidate our magic */
2876 powerContext.magic = 0;
2877 if (lrc <= 0)
2878 {
2879 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002880 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07002881 /* there is a race condition such that the callback
2882 function could be executing at the same time we are. of
2883 primary concern is if the callback function had already
2884 verified the "magic" but hasn't yet set the completion
2885 variable. Since the completion variable is on our
2886 stack, we'll delay just a bit to make sure the data is
2887 still valid if that is the case */
2888 msleep(50);
2889 }
2890 }
2891 else
2892 {
2893 hddLog(VOS_TRACE_LEVEL_ERROR,
2894 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002895 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07002896 VOS_ASSERT(0);
2897 /* continue -- need to clean up as much as possible */
2898 }
2899 }
2900
2901 // Unregister the Net Device Notifier
2902 unregister_netdevice_notifier(&hdd_netdev_notifier);
2903
Jeff Johnson295189b2012-06-20 16:38:30 -07002904 hdd_stop_all_adapters( pHddCtx );
2905
2906#ifdef ANI_BUS_TYPE_SDIO
2907 sdio_func_dev = libra_getsdio_funcdev();
2908
2909 if(sdio_func_dev == NULL)
2910 {
2911 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
2912 VOS_ASSERT(0);
2913 return;
2914 }
2915
2916 sd_claim_host(sdio_func_dev);
2917
2918 /* Disable SDIO IRQ since we are exiting */
2919 libra_enable_sdio_irq(sdio_func_dev, 0);
2920
2921 sd_release_host(sdio_func_dev);
2922#endif // ANI_BUS_TYPE_SDIO
2923
2924#ifdef WLAN_BTAMP_FEATURE
2925 vosStatus = WLANBAP_Stop(pVosContext);
2926 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2927 {
2928 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
2929 "%s: Failed to stop BAP",__func__);
2930 }
2931#endif //WLAN_BTAMP_FEATURE
2932
2933 //Stop all the modules
2934 vosStatus = vos_stop( pVosContext );
2935 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2936 {
2937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2938 "%s: Failed to stop VOSS",__func__);
2939 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2940 }
2941
2942#ifdef ANI_BUS_TYPE_SDIO
2943 vosStatus = WLANBAL_Stop( pVosContext );
2944
2945 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN BAL STOP\n");
2946 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2947 {
2948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2949 "%s: Failed to stop BAL",__func__);
2950 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2951 }
2952
2953 msleep(50);
2954 //Put the chip is standby before asserting deep sleep
2955 vosStatus = WLANBAL_SuspendChip( pVosContext );
2956
2957 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN Suspend Chip\n");
2958
2959 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2960 {
2961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2962 "%s: Failed to suspend chip ",__func__);
2963 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2964 }
2965 //Invoke SAL stop
2966 vosStatus = WLANSAL_Stop( pVosContext );
2967 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
2968 {
2969 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2970 "%s: Failed to stop SAL",__func__);
2971 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2972 }
2973
2974#endif // ANI_BUS_TYPE_SDIO
2975
2976 //Assert Deep sleep signal now to put Libra HW in lowest power state
2977 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
2978 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
2979
2980 //Vote off any PMIC voltage supplies
2981 vos_chipPowerDown(NULL, NULL, NULL);
2982
2983 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
2984
2985 //Clean up HDD Nlink Service
2986 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
2987 nl_srv_exit();
2988
2989 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07002990 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07002991
2992 //Close the scheduler before calling vos_close to make sure no thread is
2993 // scheduled after the each module close is called i.e after all the data
2994 // structures are freed.
2995 vosStatus = vos_sched_close( pVosContext );
2996 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
2997 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
2998 "%s: Failed to close VOSS Scheduler",__func__);
2999 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3000 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003001
3002#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3003 /* Destroy the wake lock */
3004 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3005#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003006 /* Destroy the wake lock */
3007 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07003008
3009 //Close VOSS
3010 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3011 vos_close(pVosContext);
3012
3013#ifdef ANI_BUS_TYPE_SDIO
3014 vosStatus = WLANBAL_Close(pVosContext);
3015 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3016 {
3017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3018 "%s: Failed to close BAL",__func__);
3019 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3020 }
3021 hddLog(VOS_TRACE_LEVEL_ERROR,"Returned WLAN BAL CLOSE\n\n\n\n");
3022#endif // ANI_BUS_TYPE_SDIO
3023
3024 //Close Watchdog
3025 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3026 vos_watchdog_close(pVosContext);
3027
3028 /* Cancel the vote for XO Core ON.
3029 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3030 * exited at this point
3031 */
3032 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3033 " when WLAN is turned OFF\n");
3034 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3035 {
3036 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3037 " Not returning failure."
3038 " Power consumed will be high\n");
3039 }
3040
3041 hdd_close_all_adapters( pHddCtx );
3042
3043
3044 //Free up dynamically allocated members inside HDD Adapter
3045 kfree(pHddCtx->cfg_ini);
3046 pHddCtx->cfg_ini= NULL;
3047
3048 /* free the power on lock from platform driver */
3049 if (free_riva_power_on_lock("wlan"))
3050 {
3051 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3052 __func__);
3053 }
3054
3055#ifdef ANI_MANF_DIAG
3056free_hdd_ctx:
3057#endif
3058#ifdef CONFIG_CFG80211
3059 wiphy_unregister(wiphy) ;
3060 wiphy_free(wiphy) ;
3061#else
3062 vos_mem_free( pHddCtx );
3063#endif
3064 if (hdd_is_ssr_required())
3065 {
3066 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003067 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003068 msleep(5000);
3069 }
3070 hdd_set_ssr_required (VOS_FALSE);
3071}
3072
3073
3074/**---------------------------------------------------------------------------
3075
3076 \brief hdd_update_config_from_nv() - Function to update the contents of
3077 the running configuration with parameters taken from NV storage
3078
3079 \param - pHddCtx - Pointer to the HDD global context
3080
3081 \return - VOS_STATUS_SUCCESS if successful
3082
3083 --------------------------------------------------------------------------*/
3084static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3085{
3086#ifndef FEATURE_WLAN_INTEGRATED_SOC
3087 eHalStatus halStatus;
3088#endif
3089
3090#ifdef FEATURE_WLAN_INTEGRATED_SOC
3091 v_BOOL_t itemIsValid = VOS_FALSE;
3092 VOS_STATUS status;
3093 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3094 v_U8_t macLoop;
3095
3096 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3097 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3098 if(status != VOS_STATUS_SUCCESS)
3099 {
3100 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3101 return VOS_STATUS_E_FAILURE;
3102 }
3103
3104 if (itemIsValid == VOS_TRUE)
3105 {
3106 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3107 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3108 VOS_MAX_CONCURRENCY_PERSONA);
3109 if(status != VOS_STATUS_SUCCESS)
3110 {
3111 /* Get MAC from NV fail, not update CFG info
3112 * INI MAC value will be used for MAC setting */
3113 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3114 return VOS_STATUS_E_FAILURE;
3115 }
3116
3117 /* If first MAC is not valid, treat all others are not valid
3118 * Then all MACs will be got from ini file */
3119 if(vos_is_macaddr_zero(&macFromNV[0]))
3120 {
3121 /* MAC address in NV file is not configured yet */
3122 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3123 return VOS_STATUS_E_INVAL;
3124 }
3125
3126 /* Get MAC address from NV, update CFG info */
3127 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3128 {
3129 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3130 {
3131 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3132 /* This MAC is not valid, skip it
3133 * This MAC will be got from ini file */
3134 }
3135 else
3136 {
3137 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3138 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3139 VOS_MAC_ADDR_SIZE);
3140 }
3141 }
3142 }
3143 else
3144 {
3145 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3146 return VOS_STATUS_E_FAILURE;
3147 }
3148#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3149
3150#ifndef FEATURE_WLAN_INTEGRATED_SOC
3151#if 1 /* need to fix for concurrency */
3152 // Set the MAC Address
3153 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3154 halStatus = ccmCfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3155 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3156 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]),
3157 hdd_set_mac_addr_cb, VOS_FALSE );
3158
3159 if (!HAL_STATUS_SUCCESS( halStatus ))
3160 {
3161 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3162 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
3163 return VOS_STATUS_E_FAILURE;
3164 }
3165#endif
3166#endif
3167
3168 return VOS_STATUS_SUCCESS;
3169}
3170
3171/**---------------------------------------------------------------------------
3172
3173 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3174
3175 \param - pAdapter - Pointer to the HDD
3176
3177 \return - None
3178
3179 --------------------------------------------------------------------------*/
3180VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3181{
3182 eHalStatus halStatus;
3183 v_U32_t listenInterval;
3184
3185#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
3186 /* In the non-integrated architecture we update the configuration from
3187 the INI file and from NV after vOSS has been started
3188 */
3189
3190 // Apply the cfg.ini to cfg.dat
3191 if (FALSE == hdd_update_config_dat(pHddCtx))
3192 {
3193 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3194 return VOS_STATUS_E_FAILURE;
3195 }
3196
3197 // Apply the NV to cfg.dat
3198 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3199 {
3200 hddLog(VOS_TRACE_LEVEL_FATAL,
3201 "%s: config update from NV failed", __func__ );
3202 return VOS_STATUS_E_FAILURE;
3203 }
3204#endif // FEATURE_WLAN_NON_INTEGRATED_SOC
3205
3206 // Send ready indication to the HDD. This will kick off the MAC
3207 // into a 'running' state and should kick off an initial scan.
3208 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3209 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3210 {
3211 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3212 "code %08d [x%08x]",__func__, halStatus, halStatus );
3213 return VOS_STATUS_E_FAILURE;
3214 }
3215
3216 // Set default LI into HDD context,
3217 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3218 // And RIVA will crash
3219 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3220 pHddCtx->hdd_actual_LI_value = listenInterval;
3221
3222 return VOS_STATUS_SUCCESS;
3223}
3224
3225#ifdef ANI_BUS_TYPE_SDIO
3226
3227#ifndef ANI_MANF_DIAG
3228// Routine to initialize the PMU
3229void wlan_hdd_enable_deepsleep(v_VOID_t * pVosContext)
3230{
3231/*-------------- Need to fix this correctly while doing Deepsleep testing
3232 tANI_U32 regValue = 0;
3233
3234 regValue = QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_DEEP_SLEEP_EN_MASK |
3235 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_AON_MASK_MASK |
3236 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_SW_MASK_MASK |
3237 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_2P3_LPM_MASK_MASK;
3238
3239 WLANBAL_WriteRegister(pVosContext, QWLAN_PMU_LDO_CTRL_REG_REG, regValue);
3240---------------------*/
3241
3242 return;
3243}
3244#endif
3245#endif
3246
3247/* wake lock APIs for HDD */
3248void hdd_prevent_suspend(void)
3249{
Jeff Johnsone7245742012-09-05 17:12:55 -07003250#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07003251 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003252#else
3253 wcnss_prevent_suspend();
3254#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003255}
3256
3257void hdd_allow_suspend(void)
3258{
Jeff Johnsone7245742012-09-05 17:12:55 -07003259#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07003260 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003261#else
3262 wcnss_allow_suspend();
3263#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003264}
3265
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003266void hdd_allow_suspend_timeout(v_U32_t timeout)
3267{
3268#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
3269 wake_lock_timeout(&wlan_wake_lock, timeout);
3270#else
3271 /* Do nothing as there is no API in wcnss for timeout*/
3272#endif
3273}
3274
Jeff Johnson295189b2012-06-20 16:38:30 -07003275/**---------------------------------------------------------------------------
3276
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003277 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3278 information between Host and Riva
3279
3280 This function gets reported version of FW
3281 It also finds the version of Riva headers used to compile the host
3282 It compares the above two and prints a warning if they are different
3283 It gets the SW and HW version string
3284 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3285 indicating the features they support through a bitmap
3286
3287 \param - pHddCtx - Pointer to HDD context
3288
3289 \return - void
3290
3291 --------------------------------------------------------------------------*/
3292
3293void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3294{
3295
3296 tSirVersionType versionCompiled;
3297 tSirVersionType versionReported;
3298 tSirVersionString versionString;
3299 tANI_U8 fwFeatCapsMsgSupported = 0;
3300 VOS_STATUS vstatus;
3301
3302 /* retrieve and display WCNSS version information */
3303 do {
3304
3305 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3306 &versionCompiled);
3307 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3308 {
3309 hddLog(VOS_TRACE_LEVEL_FATAL,
3310 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003311 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003312 break;
3313 }
3314
3315 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3316 &versionReported);
3317 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3318 {
3319 hddLog(VOS_TRACE_LEVEL_FATAL,
3320 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003321 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003322 break;
3323 }
3324
3325 if ((versionCompiled.major != versionReported.major) ||
3326 (versionCompiled.minor != versionReported.minor) ||
3327 (versionCompiled.version != versionReported.version) ||
3328 (versionCompiled.revision != versionReported.revision))
3329 {
3330 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3331 "Host expected %u.%u.%u.%u\n",
3332 WLAN_MODULE_NAME,
3333 (int)versionReported.major,
3334 (int)versionReported.minor,
3335 (int)versionReported.version,
3336 (int)versionReported.revision,
3337 (int)versionCompiled.major,
3338 (int)versionCompiled.minor,
3339 (int)versionCompiled.version,
3340 (int)versionCompiled.revision);
3341 }
3342 else
3343 {
3344 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3345 WLAN_MODULE_NAME,
3346 (int)versionReported.major,
3347 (int)versionReported.minor,
3348 (int)versionReported.version,
3349 (int)versionReported.revision);
3350 }
3351
3352 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3353 versionString,
3354 sizeof(versionString));
3355 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3356 {
3357 hddLog(VOS_TRACE_LEVEL_FATAL,
3358 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003359 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003360 break;
3361 }
3362
3363 pr_info("%s: WCNSS software version %s\n",
3364 WLAN_MODULE_NAME, versionString);
3365
3366 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3367 versionString,
3368 sizeof(versionString));
3369 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3370 {
3371 hddLog(VOS_TRACE_LEVEL_FATAL,
3372 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003373 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003374 break;
3375 }
3376
3377 pr_info("%s: WCNSS hardware version %s\n",
3378 WLAN_MODULE_NAME, versionString);
3379
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003380 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3381 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003382 send the message only if it the riva is 1.1
3383 minor numbers for different riva branches:
3384 0 -> (1.0)Mainline Build
3385 1 -> (1.1)Mainline Build
3386 2->(1.04) Stability Build
3387 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003388 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003389 ((versionReported.minor>=1) && (versionReported.version>=1)))
3390 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3391 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003392
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003393 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003394 {
3395#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3396 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3397 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3398#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003399 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003400 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003401
3402 } while (0);
3403
3404}
3405
3406/**---------------------------------------------------------------------------
3407
Jeff Johnson295189b2012-06-20 16:38:30 -07003408 \brief hdd_wlan_startup() - HDD init function
3409
3410 This is the driver startup code executed once a WLAN device has been detected
3411
3412 \param - dev - Pointer to the underlying device
3413
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003414 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003415
3416 --------------------------------------------------------------------------*/
3417
3418int hdd_wlan_startup(struct device *dev )
3419{
3420 VOS_STATUS status;
3421 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003422 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003423 hdd_context_t *pHddCtx = NULL;
3424 v_CONTEXT_t pVosContext= NULL;
3425#ifdef WLAN_BTAMP_FEATURE
3426 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3427 WLANBAP_ConfigType btAmpConfig;
3428 hdd_config_t *pConfig;
3429#endif
3430 int ret;
3431#ifdef CONFIG_CFG80211
3432 struct wiphy *wiphy;
3433#endif
3434#ifdef ANI_BUS_TYPE_SDIO
3435 struct sdio_func *sdio_func_dev = dev_to_sdio_func(dev);
3436#endif //ANI_BUS_TYPE_SDIO
3437
3438 ENTER();
3439#ifdef CONFIG_CFG80211
3440 /*
3441 * cfg80211: wiphy allocation
3442 */
3443 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3444
3445 if(wiphy == NULL)
3446 {
3447 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003448 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07003449 }
3450
3451 pHddCtx = wiphy_priv(wiphy);
3452
3453#else
3454
3455 pHddCtx = vos_mem_malloc ( sizeof( hdd_context_t ) );
3456 if(pHddCtx == NULL)
3457 {
3458 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003459 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07003460 }
3461
3462#endif
3463 //Initialize the adapter context to zeros.
3464 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
3465
3466#ifdef CONFIG_CFG80211
3467 pHddCtx->wiphy = wiphy;
3468#endif
3469 hdd_prevent_suspend();
3470 pHddCtx->isLoadUnloadInProgress = TRUE;
3471
3472 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
3473
3474 /*Get vos context here bcoz vos_open requires it*/
3475 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
3476
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08003477 if(pVosContext == NULL)
3478 {
3479 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
3480 goto err_free_hdd_context;
3481 }
3482
Jeff Johnson295189b2012-06-20 16:38:30 -07003483 //Save the Global VOSS context in adapter context for future.
3484 pHddCtx->pvosContext = pVosContext;
3485
3486 //Save the adapter context in global context for future.
3487 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
3488
3489#ifdef ANI_BUS_TYPE_SDIO
3490 // Set the private data for the device to our adapter.
3491 libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
3492 atomic_set(&pHddCtx->sdio_claim_count, 0);
3493#endif // ANI_BUS_TYPE_SDIO
3494
3495 pHddCtx->parent_dev = dev;
3496
3497 init_completion(&pHddCtx->full_pwr_comp_var);
3498 init_completion(&pHddCtx->standby_comp_var);
3499 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003500 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08003501 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07003502
3503 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
3504
3505 // Load all config first as TL config is needed during vos_open
3506 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
3507 if(pHddCtx->cfg_ini == NULL)
3508 {
3509 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
3510 goto err_free_hdd_context;
3511 }
3512
3513 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
3514
3515 // Read and parse the qcom_cfg.ini file
3516 status = hdd_parse_config_ini( pHddCtx );
3517 if ( VOS_STATUS_SUCCESS != status )
3518 {
3519 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
3520 __func__, WLAN_INI_FILE);
3521 goto err_config;
3522 }
3523
3524#ifdef CONFIG_CFG80211
3525 /*
3526 * cfg80211: Initialization and registration ...
3527 */
3528 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
3529 {
3530 hddLog(VOS_TRACE_LEVEL_FATAL,
3531 "%s: wlan_hdd_cfg80211_register return failure", __func__);
3532 goto err_wiphy_reg;
3533 }
3534#endif
3535
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08003536 // Update VOS trace levels based upon the cfg.ini
3537 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
3538 pHddCtx->cfg_ini->vosTraceEnableBAP);
3539 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
3540 pHddCtx->cfg_ini->vosTraceEnableTL);
3541 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
3542 pHddCtx->cfg_ini->vosTraceEnableWDI);
3543 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
3544 pHddCtx->cfg_ini->vosTraceEnableHDD);
3545 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
3546 pHddCtx->cfg_ini->vosTraceEnableSME);
3547 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
3548 pHddCtx->cfg_ini->vosTraceEnablePE);
3549 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
3550 pHddCtx->cfg_ini->vosTraceEnableWDA);
3551 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
3552 pHddCtx->cfg_ini->vosTraceEnableSYS);
3553 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
3554 pHddCtx->cfg_ini->vosTraceEnableVOSS);
3555#ifdef WLAN_SOFTAP_FEATURE
3556 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
3557 pHddCtx->cfg_ini->vosTraceEnableSAP);
3558 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
3559 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
3560#endif
3561
Jeff Johnson295189b2012-06-20 16:38:30 -07003562#ifdef FEATURE_WLAN_INTEGRATED_SOC
3563 // Update WDI trace levels based upon the cfg.ini
3564 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
3565 pHddCtx->cfg_ini->wdiTraceEnableDAL);
3566 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
3567 pHddCtx->cfg_ini->wdiTraceEnableCTL);
3568 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
3569 pHddCtx->cfg_ini->wdiTraceEnableDAT);
3570 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
3571 pHddCtx->cfg_ini->wdiTraceEnablePAL);
3572#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3573
3574#ifdef ANI_MANF_DIAG
3575 if(VOS_FTM_MODE == hdd_get_conparam())
3576 {
3577 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
3578 {
3579 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
3580 goto err_free_hdd_context;
3581 }
3582 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
3583 return VOS_STATUS_SUCCESS;
3584 }
3585#endif
3586
3587 //Open watchdog module
3588 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3589 {
3590 status = vos_watchdog_open(pVosContext,
3591 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
3592
3593 if(!VOS_IS_STATUS_SUCCESS( status ))
3594 {
3595 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
3596#ifdef CONFIG_CFG80211
3597 goto err_wiphy_reg;
3598#else
3599 goto err_config;
3600#endif
3601 }
3602 }
3603
3604 pHddCtx->isLogpInProgress = FALSE;
3605 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
3606
3607#ifdef ANI_BUS_TYPE_SDIO
3608 status = WLANBAL_Open(pHddCtx->pvosContext);
3609 if(!VOS_IS_STATUS_SUCCESS(status))
3610 {
3611 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3612 "%s: Failed to open BAL",__func__);
3613 goto err_wdclose;
3614 }
3615#endif // ANI_BUS_TYPE_SDIO
3616
3617 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
3618 if(!VOS_IS_STATUS_SUCCESS(status))
3619 {
3620 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
3621#ifdef ANI_BUS_TYPE_SDIO
3622 goto err_balclose;
3623#else
3624 goto err_wdclose;
3625#endif
3626 }
3627
3628
3629#ifdef ANI_BUS_TYPE_SDIO
3630 status = WLANSAL_Start(pHddCtx->pvosContext);
3631 if (!VOS_IS_STATUS_SUCCESS(status))
3632 {
3633 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
3634 goto err_clkvote;
3635 }
3636
3637 /* Start BAL */
3638 status = WLANBAL_Start(pHddCtx->pvosContext);
3639
3640 if (!VOS_IS_STATUS_SUCCESS(status))
3641 {
3642 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3643 "%s: Failed to start BAL",__func__);
3644 goto err_salstop;
3645 }
3646#endif // ANI_BUS_TYPE_SDIO
3647
3648#ifdef MSM_PLATFORM_7x30
3649 /* FIXME: Volans 2.0 configuration. Reconfigure 1.3v SW supply to 1.3v. It will be configured to
3650 * 1.4v in vos_ChipPowerup() routine above
3651 */
3652#endif
3653
3654 status = vos_open( &pVosContext, 0);
3655 if ( !VOS_IS_STATUS_SUCCESS( status ))
3656 {
3657 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
3658 goto err_balstop;
3659 }
3660
3661 /* Save the hal context in Adapter */
3662 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
3663
3664 if ( NULL == pHddCtx->hHal )
3665 {
3666 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
3667 goto err_vosclose;
3668 }
3669
Jeff Johnsone7245742012-09-05 17:12:55 -07003670#ifdef FEATURE_WLAN_INTEGRATED_SOC
3671 /* Vos preStart is calling */
3672 /* vos preStart which does cfg download should be called before set sme config which accesses/sets some cfgs */
3673 status = vos_preStart( pHddCtx->pvosContext );
3674 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3675 {
3676 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
3677 goto err_vosclose;
3678 }
3679#endif
3680
Jeff Johnson295189b2012-06-20 16:38:30 -07003681 // Set the SME configuration parameters...
3682 status = hdd_set_sme_config( pHddCtx );
3683
3684 if ( VOS_STATUS_SUCCESS != status )
3685 {
3686 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
3687 goto err_vosclose;
3688 }
3689
3690 //Initialize the WMM module
3691 status = hdd_wmm_init(pHddCtx);
3692 if (!VOS_IS_STATUS_SUCCESS(status))
3693 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003694 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003695 goto err_vosclose;
3696 }
3697
3698#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnson295189b2012-06-20 16:38:30 -07003699 /* In the integrated architecture we update the configuration from
3700 the INI file and from NV before vOSS has been started so that
3701 the final contents are available to send down to the cCPU */
3702
3703 // Apply the cfg.ini to cfg.dat
3704 if (FALSE == hdd_update_config_dat(pHddCtx))
3705 {
3706 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3707 goto err_vosclose;
3708 }
3709
3710 // Apply the NV to cfg.dat
3711 /* Prima Update MAC address only at here */
3712 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3713 {
3714#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
3715 /* There was not a valid set of MAC Addresses in NV. See if the
3716 default addresses were modified by the cfg.ini settings. If so,
3717 we'll use them, but if not, we'll autogenerate a set of MAC
3718 addresses based upon the device serial number */
3719
3720 static const v_MACADDR_t default_address =
3721 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
3722 unsigned int serialno;
3723 int i;
3724
3725 serialno = wcnss_get_serial_number();
3726 if ((0 != serialno) &&
3727 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
3728 sizeof(default_address))))
3729 {
3730 /* cfg.ini has the default address, invoke autogen logic */
3731
3732 /* MAC address has 3 bytes of OUI so we have a maximum of 3
3733 bytes of the serial number that can be used to generate
3734 the other 3 bytes of the MAC address. Mask off all but
3735 the lower 3 bytes (this will also make sure we don't
3736 overflow in the next step) */
3737 serialno &= 0x00FFFFFF;
3738
3739 /* we need a unique address for each session */
3740 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
3741
3742 /* autogen all addresses */
3743 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
3744 {
3745 /* start with the entire default address */
3746 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
3747 /* then replace the lower 3 bytes */
3748 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
3749 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
3750 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
3751
3752 serialno++;
3753 }
3754
3755 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
3756 MAC_ADDRESS_STR,
3757 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
3758 }
3759 else
3760#endif //WLAN_AUTOGEN_MACADDR_FEATURE
3761 {
3762 hddLog(VOS_TRACE_LEVEL_ERROR,
3763 "%s: Invalid MAC address in NV, using MAC from ini file "
3764 MAC_ADDRESS_STR, __func__,
3765 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
3766 }
3767 }
3768 {
3769 eHalStatus halStatus;
3770 // Set the MAC Address
3771 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3772 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3773 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3774 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
3775
3776 if (!HAL_STATUS_SUCCESS( halStatus ))
3777 {
3778 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3779 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08003780 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07003781 }
3782 }
3783#endif // FEATURE_WLAN_INTEGRATED_SOC
3784
3785 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
3786 Note: Firmware image will be read and downloaded inside vos_start API */
3787 status = vos_start( pHddCtx->pvosContext );
3788 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3789 {
3790 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
3791 goto err_vosclose;
3792 }
3793
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003794 /* Exchange capability info between Host and FW and also get versioning info from FW */
3795 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003796
3797 status = hdd_post_voss_start_config( pHddCtx );
3798 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3799 {
3800 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
3801 __func__);
3802 goto err_vosstop;
3803 }
3804
3805#ifdef WLAN_SOFTAP_FEATURE
3806 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3807 {
3808 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
3809 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
3810 }
3811 else
3812 {
3813#endif
3814 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
3815 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
3816 if (pAdapter != NULL)
3817 {
3818#ifdef WLAN_FEATURE_P2P
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05303819 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07003820 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05303821 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
3822 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
3823 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07003824
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05303825 /* Generate the P2P Device Address. This consists of the device's
3826 * primary MAC address with the locally administered bit set.
3827 */
3828 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07003829 }
3830 else
3831 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05303832 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
3833 if (p2p_dev_addr != NULL)
3834 {
3835 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
3836 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
3837 }
3838 else
3839 {
3840 hddLog(VOS_TRACE_LEVEL_FATAL,
3841 "%s: Failed to allocate mac_address for p2p_device",
3842 __func__);
3843 goto err_close_adapter;
3844 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003845 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003846
3847 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
3848 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
3849 if ( NULL == pP2pAdapter )
3850 {
3851 hddLog(VOS_TRACE_LEVEL_FATAL,
3852 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003853 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07003854 goto err_close_adapter;
3855 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003856#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07003857 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003858#ifdef WLAN_SOFTAP_FEATURE
3859 }
3860#endif
3861
3862 if( pAdapter == NULL )
3863 {
3864 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
3865#ifdef ANI_BUS_TYPE_SDIO
3866 goto err_balstop;
3867#else
3868 goto err_clkvote;
3869#endif
3870 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003871
Jeff Johnson295189b2012-06-20 16:38:30 -07003872#ifdef WLAN_BTAMP_FEATURE
3873 vStatus = WLANBAP_Open(pVosContext);
3874 if(!VOS_IS_STATUS_SUCCESS(vStatus))
3875 {
3876 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3877 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07003878 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003879 }
3880
3881 vStatus = BSL_Init(pVosContext);
3882 if(!VOS_IS_STATUS_SUCCESS(vStatus))
3883 {
3884 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3885 "%s: Failed to Init BSL",__func__);
3886 goto err_bap_close;
3887 }
3888 vStatus = WLANBAP_Start(pVosContext);
3889 if (!VOS_IS_STATUS_SUCCESS(vStatus))
3890 {
3891 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3892 "%s: Failed to start TL",__func__);
3893 goto err_bap_close;
3894 }
3895
3896 pConfig = pHddCtx->cfg_ini;
3897 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
3898 status = WLANBAP_SetConfig(&btAmpConfig);
3899
3900#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07003901
Jeff Johnson295189b2012-06-20 16:38:30 -07003902#ifdef FEATURE_WLAN_SCAN_PNO
3903 /*SME must send channel update configuration to RIVA*/
3904 sme_UpdateChannelConfig(pHddCtx->hHal);
3905#endif
3906
3907#ifdef FEATURE_WLAN_INTEGRATED_SOC
3908 /* Register with platform driver as client for Suspend/Resume */
3909 status = hddRegisterPmOps(pHddCtx);
3910 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3911 {
3912 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
3913#ifdef WLAN_BTAMP_FEATURE
3914 goto err_bap_stop;
3915#else
Jeff Johnsone7245742012-09-05 17:12:55 -07003916 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07003917#endif //WLAN_BTAMP_FEATURE
3918 }
3919
3920 /* Register TM level change handler function to the platform */
3921 status = hddDevTmRegisterNotifyCallback(pHddCtx);
3922 if ( !VOS_IS_STATUS_SUCCESS( status ) )
3923 {
3924 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
3925 goto err_unregister_pmops;
3926 }
3927#endif
3928
3929 /* register for riva power on lock to platform driver */
3930 if (req_riva_power_on_lock("wlan"))
3931 {
3932 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
3933 __func__);
3934 goto err_unregister_pmops;
3935 }
3936
Jeff Johnson295189b2012-06-20 16:38:30 -07003937 // register net device notifier for device change notification
3938 ret = register_netdevice_notifier(&hdd_netdev_notifier);
3939
3940 if(ret < 0)
3941 {
3942 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
3943 goto err_free_power_on_lock;
3944 }
3945
3946 //Initialize the nlink service
3947 if(nl_srv_init() != 0)
3948 {
3949 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
3950 goto err_reg_netdev;
3951 }
3952
3953 //Initialize the BTC service
3954 if(btc_activate_service(pHddCtx) != 0)
3955 {
3956 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
3957 goto err_nl_srv;
3958 }
3959
3960#ifdef PTT_SOCK_SVC_ENABLE
3961 //Initialize the PTT service
3962 if(ptt_sock_activate_svc(pHddCtx) != 0)
3963 {
3964 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
3965 goto err_nl_srv;
3966 }
3967#endif
3968
Jeff Johnson295189b2012-06-20 16:38:30 -07003969 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003970#ifdef CONFIG_CFG80211
3971#ifdef WLAN_SOFTAP_FEATURE
3972 if (VOS_STA_SAP_MODE != hdd_get_conparam())
3973#endif
3974 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07003975 /* Action frame registered in one adapter which will
3976 * applicable to all interfaces
3977 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07003978 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07003979 }
3980#endif
3981
3982 mutex_init(&pHddCtx->sap_lock);
3983
3984 pHddCtx->isLoadUnloadInProgress = FALSE;
3985
Jeff Johnsone7245742012-09-05 17:12:55 -07003986#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3987 /* Initialize the wake lcok */
3988 wake_lock_init(&pHddCtx->rx_wake_lock,
3989 WAKE_LOCK_SUSPEND,
3990 "qcom_rx_wakelock");
3991#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003992 /* Initialize the wake lcok */
3993 wake_lock_init(&pHddCtx->sap_wake_lock,
3994 WAKE_LOCK_SUSPEND,
3995 "qcom_sap_wakelock");
Jeff Johnsone7245742012-09-05 17:12:55 -07003996
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07003997 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
3998 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07003999
4000 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4001 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004002
4003 // Initialize the restart logic
4004 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304005
4006#ifdef FEATURE_WLAN_TDLS
Hoonki Lee387663d2013-02-05 18:08:43 -08004007 if(0 != wlan_hdd_tdls_init(pAdapter->dev))
4008 {
4009 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_tdls_init failed",__func__);
4010 goto err_nl_srv;
4011 }
Chilam NG571c65a2013-01-19 12:27:36 +05304012#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004013
4014 goto success;
4015
4016err_nl_srv:
4017 nl_srv_exit();
4018
4019err_reg_netdev:
4020 unregister_netdevice_notifier(&hdd_netdev_notifier);
4021
4022err_free_power_on_lock:
4023 free_riva_power_on_lock("wlan");
4024
4025err_unregister_pmops:
4026 hddDevTmUnregisterNotifyCallback(pHddCtx);
4027 hddDeregisterPmOps(pHddCtx);
4028
4029#ifdef WLAN_BTAMP_FEATURE
4030err_bap_stop:
4031 WLANBAP_Stop(pVosContext);
4032#endif
4033
4034#ifdef WLAN_BTAMP_FEATURE
4035err_bap_close:
4036 WLANBAP_Close(pVosContext);
4037#endif
4038
Jeff Johnson295189b2012-06-20 16:38:30 -07004039err_close_adapter:
4040 hdd_close_all_adapters( pHddCtx );
4041
4042err_vosstop:
4043 vos_stop(pVosContext);
4044
4045err_vosclose:
4046 status = vos_sched_close( pVosContext );
4047 if (!VOS_IS_STATUS_SUCCESS(status)) {
4048 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4049 "%s: Failed to close VOSS Scheduler", __func__);
4050 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4051 }
4052 vos_close(pVosContext );
4053
4054err_balstop:
4055#ifdef ANI_BUS_TYPE_SDIO
4056#ifndef ANI_MANF_DIAG
4057 wlan_hdd_enable_deepsleep(pHddCtx->pvosContext);
4058#endif
4059
4060 WLANBAL_Stop(pHddCtx->pvosContext);
4061 WLANBAL_SuspendChip(pHddCtx->pvosContext);
4062#endif
4063
4064#ifdef ANI_BUS_TYPE_SDIO
4065err_salstop:
4066 WLANSAL_Stop(pHddCtx->pvosContext);
4067
4068#endif
4069err_clkvote:
4070 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4071
4072#ifdef ANI_BUS_TYPE_SDIO
4073err_balclose:
4074 WLANBAL_Close(pHddCtx->pvosContext);
4075#endif // ANI_BUS_TYPE_SDIO
4076
4077err_wdclose:
4078 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4079 vos_watchdog_close(pVosContext);
4080
4081#ifdef CONFIG_CFG80211
4082err_wiphy_reg:
4083 wiphy_unregister(wiphy) ;
4084#endif
4085
4086err_config:
4087 kfree(pHddCtx->cfg_ini);
4088 pHddCtx->cfg_ini= NULL;
4089
4090err_free_hdd_context:
4091 hdd_allow_suspend();
4092#ifdef CONFIG_CFG80211
4093 wiphy_free(wiphy) ;
4094 //kfree(wdev) ;
4095#else
4096 vos_mem_free( pHddCtx );
4097#endif
4098 VOS_BUG(1);
4099
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004100 if (hdd_is_ssr_required())
4101 {
4102 /* WDI timeout had happened during load, so SSR is needed here */
4103 subsystem_restart("wcnss");
4104 msleep(5000);
4105 }
4106 hdd_set_ssr_required (VOS_FALSE);
4107
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004108 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004109
4110success:
4111 EXIT();
4112 return 0;
4113}
4114
4115/**---------------------------------------------------------------------------
4116
Jeff Johnson32d95a32012-09-10 13:15:23 -07004117 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004118
Jeff Johnson32d95a32012-09-10 13:15:23 -07004119 This is the driver entry point - called in different timeline depending
4120 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004121
4122 \param - None
4123
4124 \return - 0 for success, non zero for failure
4125
4126 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004127static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004128{
4129 VOS_STATUS status;
4130 v_CONTEXT_t pVosContext = NULL;
4131#ifdef ANI_BUS_TYPE_SDIO
4132 struct sdio_func *sdio_func_dev = NULL;
4133 unsigned int attempts = 0;
4134#endif // ANI_BUS_TYPE_SDIO
4135 struct device *dev = NULL;
4136 int ret_status = 0;
4137
4138 ENTER();
4139
Jeff Johnsone7245742012-09-05 17:12:55 -07004140#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07004141 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004142#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004143
4144 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4145 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4146
4147 //Power Up Libra WLAN card first if not already powered up
4148 status = vos_chipPowerUp(NULL,NULL,NULL);
4149 if (!VOS_IS_STATUS_SUCCESS(status))
4150 {
4151 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4152 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004153 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004154 }
4155
4156#ifdef ANI_BUS_TYPE_SDIO
4157 //SDIO Polling should be turned on for card detection. When using Android Wi-Fi GUI
4158 //users need not trigger SDIO polling explicitly. However when loading drivers via
4159 //command line (Adb shell), users must turn on SDIO polling prior to loading WLAN.
4160 do {
4161 sdio_func_dev = libra_getsdio_funcdev();
4162 if (NULL == sdio_func_dev) {
4163 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
4164 attempts++;
4165 }
4166 else {
4167 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
4168 dev = &sdio_func_dev->dev;
4169 break;
4170 }
4171
4172 if(attempts == 7)
4173 break;
4174
4175 msleep(250);
4176
4177 }while (attempts < 7);
4178
4179 //Retry to detect the card again by Powering Down the chip and Power up the chip
4180 //again. This retry is done to recover from CRC Error
4181 if (NULL == sdio_func_dev) {
4182
4183 attempts = 0;
4184
4185 //Vote off any PMIC voltage supplies
4186 vos_chipPowerDown(NULL, NULL, NULL);
4187
4188 msleep(1000);
4189
4190 //Power Up Libra WLAN card first if not already powered up
4191 status = vos_chipPowerUp(NULL,NULL,NULL);
4192 if (!VOS_IS_STATUS_SUCCESS(status))
4193 {
4194 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
4195 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004196 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004197 }
4198
4199 do {
4200 sdio_func_dev = libra_getsdio_funcdev();
4201 if (NULL == sdio_func_dev) {
4202 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
4203 attempts++;
4204 }
4205 else {
4206 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
4207 dev = &sdio_func_dev->dev;
4208 break;
4209 }
4210
4211 if(attempts == 2)
4212 break;
4213
4214 msleep(1000);
4215
4216 }while (attempts < 3);
4217 }
4218
4219#endif // ANI_BUS_TYPE_SDIO
4220
4221#ifdef ANI_BUS_TYPE_PCI
4222
4223 dev = wcnss_wlan_get_device();
4224
4225#endif // ANI_BUS_TYPE_PCI
4226
4227#ifdef ANI_BUS_TYPE_PLATFORM
4228 dev = wcnss_wlan_get_device();
4229#endif // ANI_BUS_TYPE_PLATFORM
4230
4231
4232 do {
4233 if (NULL == dev) {
4234 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4235 ret_status = -1;
4236 break;
4237 }
4238
4239#ifdef MEMORY_DEBUG
4240 vos_mem_init();
4241#endif
4242
4243#ifdef TIMER_MANAGER
4244 vos_timer_manager_init();
4245#endif
4246
4247 /* Preopen VOSS so that it is ready to start at least SAL */
4248 status = vos_preOpen(&pVosContext);
4249
4250 if (!VOS_IS_STATUS_SUCCESS(status))
4251 {
4252 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4253 ret_status = -1;
4254 break;
4255 }
4256
4257#ifdef ANI_BUS_TYPE_SDIO
4258 /* Now Open SAL */
4259 status = WLANSAL_Open(pVosContext, 0);
4260
4261 if(!VOS_IS_STATUS_SUCCESS(status))
4262 {
4263 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to open SAL", __func__);
4264
4265 /* If unable to open, cleanup and return failure */
4266 vos_preClose( &pVosContext );
4267 ret_status = -1;
4268 break;
4269 }
4270#endif // ANI_BUS_TYPE_SDIO
4271
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004272#ifndef MODULE
4273 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4274 */
4275 hdd_set_conparam((v_UINT_t)con_mode);
4276#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004277
4278 // Call our main init function
4279 if(hdd_wlan_startup(dev)) {
4280 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
4281 __func__);
4282#ifdef ANI_BUS_TYPE_SDIO
4283 WLANSAL_Close(pVosContext);
4284#endif // ANI_BUS_TYPE_SDIO
4285 vos_preClose( &pVosContext );
4286 ret_status = -1;
4287 break;
4288 }
4289
4290 /* Cancel the vote for XO Core ON
4291 * This is done here for safety purposes in case we re-initialize without turning
4292 * it OFF in any error scenario.
4293 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004294 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004295 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004296 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004297 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4298 {
4299 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4300 " Power consumed will be high\n");
4301 }
4302 } while (0);
4303
4304 if (0 != ret_status)
4305 {
4306 //Assert Deep sleep signal now to put Libra HW in lowest power state
4307 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4308 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4309
4310 //Vote off any PMIC voltage supplies
4311 vos_chipPowerDown(NULL, NULL, NULL);
4312#ifdef TIMER_MANAGER
4313 vos_timer_exit();
4314#endif
4315#ifdef MEMORY_DEBUG
4316 vos_mem_exit();
4317#endif
4318
Jeff Johnsone7245742012-09-05 17:12:55 -07004319#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07004320 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004321#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004322 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4323 }
4324 else
4325 {
4326 //Send WLAN UP indication to Nlink Service
4327 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4328
4329 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4330
4331 }
4332
4333 EXIT();
4334
4335 return ret_status;
4336}
4337
Jeff Johnson32d95a32012-09-10 13:15:23 -07004338/**---------------------------------------------------------------------------
4339
4340 \brief hdd_module_init() - Init Function
4341
4342 This is the driver entry point (invoked when module is loaded using insmod)
4343
4344 \param - None
4345
4346 \return - 0 for success, non zero for failure
4347
4348 --------------------------------------------------------------------------*/
4349#ifdef MODULE
4350static int __init hdd_module_init ( void)
4351{
4352 return hdd_driver_init();
4353}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004354#else /* #ifdef MODULE */
4355static int __init hdd_module_init ( void)
4356{
4357 /* Driver initialization is delayed to fwpath_changed_handler */
4358 return 0;
4359}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004360#endif /* #ifdef MODULE */
4361
Jeff Johnson295189b2012-06-20 16:38:30 -07004362
4363/**---------------------------------------------------------------------------
4364
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004365 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004366
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004367 This is the driver exit point (invoked when module is unloaded using rmmod
4368 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004369
4370 \param - None
4371
4372 \return - None
4373
4374 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004375static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004376{
4377 hdd_context_t *pHddCtx = NULL;
4378 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004379
4380 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4381
4382 //Get the global vos context
4383 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4384
4385 if(!pVosContext)
4386 {
4387 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4388 goto done;
4389 }
4390
4391 //Get the HDD context.
4392 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4393
4394 if(!pHddCtx)
4395 {
4396 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4397 }
4398 else
4399 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004400 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004401 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004402 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4403 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004404 }
4405
4406 pHddCtx->isLoadUnloadInProgress = TRUE;
4407 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4408
4409 //Do all the cleanup before deregistering the driver
4410 hdd_wlan_exit(pHddCtx);
4411 }
4412
4413#ifdef ANI_BUS_TYPE_SDIO
4414 WLANSAL_Close(pVosContext);
4415#endif // ANI_BUS_TYPE_SDIO
4416
4417 vos_preClose( &pVosContext );
4418
4419#ifdef TIMER_MANAGER
4420 vos_timer_exit();
4421#endif
4422#ifdef MEMORY_DEBUG
4423 vos_mem_exit();
4424#endif
4425
4426done:
Jeff Johnsone7245742012-09-05 17:12:55 -07004427#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,5))
Jeff Johnson295189b2012-06-20 16:38:30 -07004428 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004429#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004430 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4431}
4432
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004433/**---------------------------------------------------------------------------
4434
4435 \brief hdd_module_exit() - Exit function
4436
4437 This is the driver exit point (invoked when module is unloaded using rmmod)
4438
4439 \param - None
4440
4441 \return - None
4442
4443 --------------------------------------------------------------------------*/
4444static void __exit hdd_module_exit(void)
4445{
4446 hdd_driver_exit();
4447}
4448
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004449#ifdef MODULE
4450static int fwpath_changed_handler(const char *kmessage,
4451 struct kernel_param *kp)
4452{
4453 /* nothing to do when driver is DLKM */
4454 return 0;
4455}
4456
4457static int con_mode_handler(const char *kmessage,
4458 struct kernel_param *kp)
4459{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07004460 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004461}
4462#else /* #ifdef MODULE */
4463/**---------------------------------------------------------------------------
4464
4465 \brief fwpath_changed_handler() - Handler Function
4466
4467 This is the driver entry point
4468 - delayed driver initialization when driver is statically linked
4469 - invoked when module parameter fwpath is modified from userpspace to signal
4470 initializing the WLAN driver
4471
4472 \return - 0 for success, non zero for failure
4473
4474 --------------------------------------------------------------------------*/
4475static int fwpath_changed_handler(const char *kmessage,
4476 struct kernel_param *kp)
4477{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004478 int ret_status;
4479
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004480 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004481 ret_status = hdd_driver_init();
4482 wlan_hdd_inited = ret_status ? 0 : 1;
4483 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004484 }
4485
4486 hdd_driver_exit();
4487
4488 msleep(200);
4489
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07004490 ret_status = hdd_driver_init();
4491 wlan_hdd_inited = ret_status ? 0 : 1;
4492 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004493}
4494
Jeff Johnson295189b2012-06-20 16:38:30 -07004495/**---------------------------------------------------------------------------
4496
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004497 \brief con_mode_handler() -
4498
4499 Handler function for module param con_mode when it is changed by userspace
4500 Dynamically linked - do nothing
4501 Statically linked - exit and init driver, as in rmmod and insmod
4502
4503 \param -
4504
4505 \return -
4506
4507 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004508static int con_mode_handler(const char *kmessage,
4509 struct kernel_param *kp)
4510{
4511 int ret = param_set_int(kmessage, kp);
4512
4513 if (ret)
4514 return ret;
4515
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07004516 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004517}
4518#endif /* #ifdef MODULE */
4519
4520/**---------------------------------------------------------------------------
4521
Jeff Johnson295189b2012-06-20 16:38:30 -07004522 \brief hdd_get_conparam() -
4523
4524 This is the driver exit point (invoked when module is unloaded using rmmod)
4525
4526 \param - None
4527
4528 \return - tVOS_CON_MODE
4529
4530 --------------------------------------------------------------------------*/
4531tVOS_CON_MODE hdd_get_conparam ( void )
4532{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004533#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07004534 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004535#else
4536 return (tVOS_CON_MODE)curr_con_mode;
4537#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004538}
4539void hdd_set_conparam ( v_UINT_t newParam )
4540{
4541 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004542#ifndef MODULE
4543 curr_con_mode = con_mode;
4544#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004545}
4546/**---------------------------------------------------------------------------
4547
4548 \brief hdd_softap_sta_deauth() - function
4549
4550 This to take counter measure to handle deauth req from HDD
4551
4552 \param - pAdapter - Pointer to the HDD
4553
4554 \param - enable - boolean value
4555
4556 \return - None
4557
4558 --------------------------------------------------------------------------*/
4559
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004560VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07004561{
Jeff Johnson295189b2012-06-20 16:38:30 -07004562 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004563 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07004564#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
4565 tHalHandle hHalHandle;
4566#endif
4567
4568 ENTER();
4569
4570 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4571
4572 //Ignore request to deauth bcmc station
4573 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004574 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004575
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004576 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07004577
4578 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08004579 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07004580}
4581
4582/**---------------------------------------------------------------------------
4583
4584 \brief hdd_softap_sta_disassoc() - function
4585
4586 This to take counter measure to handle deauth req from HDD
4587
4588 \param - pAdapter - Pointer to the HDD
4589
4590 \param - enable - boolean value
4591
4592 \return - None
4593
4594 --------------------------------------------------------------------------*/
4595
4596void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
4597{
4598 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4599
4600 ENTER();
4601
4602 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4603
4604 //Ignore request to disassoc bcmc station
4605 if( pDestMacAddress[0] & 0x1 )
4606 return;
4607
4608 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
4609}
4610
4611void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
4612{
4613 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
4614
4615 ENTER();
4616
4617 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
4618
4619 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
4620}
4621
Jeff Johnson295189b2012-06-20 16:38:30 -07004622/**---------------------------------------------------------------------------
4623 *
4624 * \brief hdd_get__concurrency_mode() -
4625 *
4626 *
4627 * \param - None
4628 *
4629 * \return - CONCURRENCY MODE
4630 *
4631 * --------------------------------------------------------------------------*/
4632tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
4633{
4634 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
4635 hdd_context_t *pHddCtx;
4636
4637 if (NULL != pVosContext)
4638 {
4639 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
4640 if (NULL != pHddCtx)
4641 {
4642 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
4643 }
4644 }
4645
4646 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004647 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004648 return VOS_STA;
4649}
4650
4651/* Decide whether to allow/not the apps power collapse.
4652 * Allow apps power collapse if we are in connected state.
4653 * if not, allow only if we are in IMPS */
4654v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
4655{
4656 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08004657 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07004658 hdd_config_t *pConfig = pHddCtx->cfg_ini;
4659 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4660 hdd_adapter_t *pAdapter = NULL;
4661 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08004662 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07004663
4664#ifdef WLAN_SOFTAP_FEATURE
4665 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4666 return TRUE;
4667#endif
4668
Yathish9f22e662012-12-10 14:21:35 -08004669 concurrent_state = hdd_get_concurrency_mode();
4670
4671#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
4672 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
4673 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
4674 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
4675 return TRUE;
4676#endif
4677
Jeff Johnson295189b2012-06-20 16:38:30 -07004678 /*loop through all adapters. TBD fix for Concurrency */
4679 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4680 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
4681 {
4682 pAdapter = pAdapterNode->pAdapter;
4683 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
4684 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
4685 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004686 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07004687 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08004688 && pmcState != STOPPED && pmcState != STANDBY)) ||
4689 (eANI_BOOLEAN_TRUE == scanRspPending))
Jeff Johnson295189b2012-06-20 16:38:30 -07004690 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08004691 hddLog( LOGE, "%s: do not allow APPS power collapse-"
4692 "pmcState = %d scanRspPending = %d",
4693 __func__, pmcState, scanRspPending );
Jeff Johnson295189b2012-06-20 16:38:30 -07004694 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);