blob: b935fd2c7e580f259de6cc8de29c1ede3fced631 [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 */
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800179#ifdef WLAN_OPEN_SOURCE
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);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800202#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
203void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
204static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
205static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
206#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700207static int hdd_netdev_notifier_call(struct notifier_block * nb,
208 unsigned long state,
209 void *ndev)
210{
211 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700212 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
213 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -0700214#ifdef WLAN_BTAMP_FEATURE
215 VOS_STATUS status;
216 hdd_context_t *pHddCtx;
217#endif
218
219 //Make sure that this callback corresponds to our device.
220 if((strncmp( dev->name, "wlan", 4 )) &&
Jeff Johnsone7245742012-09-05 17:12:55 -0700221 (strncmp( dev->name, "p2p", 3))
Jeff Johnson295189b2012-06-20 16:38:30 -0700222 )
223 return NOTIFY_DONE;
224
225#ifdef CONFIG_CFG80211
226 if (!dev->ieee80211_ptr)
227 return NOTIFY_DONE;
228#endif
229
Jeff Johnson295189b2012-06-20 16:38:30 -0700230
231 if(NULL == pAdapter)
232 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800233 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700234 VOS_ASSERT(0);
235 return NOTIFY_DONE;
236 }
237
238 hddLog(VOS_TRACE_LEVEL_INFO,"%s: New Net Device State = %lu", __func__, state);
239
240 switch (state) {
241 case NETDEV_REGISTER:
242 break;
243
244 case NETDEV_UNREGISTER:
245 break;
246
247 case NETDEV_UP:
248 break;
249
250 case NETDEV_DOWN:
251 break;
252
253 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700254 if(TRUE == pAdapter->isLinkUpSvcNeeded)
255 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700256 break;
257
258 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700259 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700260 {
261 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800262 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700263 hdd_abort_mac_scan(pAdapter->pHddCtx);
264 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800265 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700266 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
267 if(!result)
268 {
269 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800270 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700271 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700272 }
273 }
274 else
275 {
276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700277 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 }
279#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700280 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700281 status = WLANBAP_StopAmp();
282 if(VOS_STATUS_SUCCESS != status )
283 {
284 pHddCtx->isAmpAllowed = VOS_TRUE;
285 hddLog(VOS_TRACE_LEVEL_FATAL,
286 "%s: Failed to stop AMP", __func__);
287 }
288 else
289 {
290 //a state m/c implementation in PAL is TBD to avoid this delay
291 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700292 if ( pHddCtx->isAmpAllowed )
293 {
294 WLANBAP_DeregisterFromHCI();
295 pHddCtx->isAmpAllowed = VOS_FALSE;
296 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700297 }
298#endif //WLAN_BTAMP_FEATURE
299 break;
300
301 default:
302 break;
303 }
304
305 return NOTIFY_DONE;
306}
307
308struct notifier_block hdd_netdev_notifier = {
309 .notifier_call = hdd_netdev_notifier_call,
310};
311
312/*---------------------------------------------------------------------------
313 * Function definitions
314 *-------------------------------------------------------------------------*/
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800315int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700316void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
317void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700318//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700319static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700320#ifndef MODULE
321/* current con_mode - used only for statically linked driver
322 * con_mode is changed by userspace to indicate a mode change which will
323 * result in calling the module exit and init functions. The module
324 * exit function will clean up based on the value of con_mode prior to it
325 * being changed by userspace. So curr_con_mode records the current con_mode
326 * for exit when con_mode becomes the next mode for init
327 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700328static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700329#endif
330
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800331/**---------------------------------------------------------------------------
332
333 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
334
335 Called immediately after the cfg.ini is read in order to configure
336 the desired trace levels.
337
338 \param - moduleId - module whose trace level is being configured
339 \param - bitmask - bitmask of log levels to be enabled
340
341 \return - void
342
343 --------------------------------------------------------------------------*/
344static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
345{
346 wpt_tracelevel level;
347
348 /* if the bitmask is the default value, then a bitmask was not
349 specified in cfg.ini, so leave the logging level alone (it
350 will remain at the "compiled in" default value) */
351 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
352 {
353 return;
354 }
355
356 /* a mask was specified. start by disabling all logging */
357 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
358
359 /* now cycle through the bitmask until all "set" bits are serviced */
360 level = VOS_TRACE_LEVEL_FATAL;
361 while (0 != bitmask)
362 {
363 if (bitmask & 1)
364 {
365 vos_trace_setValue(moduleId, level, 1);
366 }
367 level++;
368 bitmask >>= 1;
369 }
370}
371
372
Jeff Johnson295189b2012-06-20 16:38:30 -0700373#ifdef FEATURE_WLAN_INTEGRATED_SOC
374/**---------------------------------------------------------------------------
375
376 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
377
378 Called immediately after the cfg.ini is read in order to configure
379 the desired trace levels in the WDI.
380
381 \param - moduleId - module whose trace level is being configured
382 \param - bitmask - bitmask of log levels to be enabled
383
384 \return - void
385
386 --------------------------------------------------------------------------*/
387static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
388{
389 wpt_tracelevel level;
390
391 /* if the bitmask is the default value, then a bitmask was not
392 specified in cfg.ini, so leave the logging level alone (it
393 will remain at the "compiled in" default value) */
394 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
395 {
396 return;
397 }
398
399 /* a mask was specified. start by disabling all logging */
400 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
401
402 /* now cycle through the bitmask until all "set" bits are serviced */
403 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
404 while (0 != bitmask)
405 {
406 if (bitmask & 1)
407 {
408 wpalTraceSetLevel(moduleId, level, 1);
409 }
410 level++;
411 bitmask >>= 1;
412 }
413}
414#endif /* FEATURE_WLAN_INTEGRATED_SOC */
415
416int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
417{
418 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
419 hdd_priv_data_t priv_data;
420 tANI_U8 *command = NULL;
421 int ret = 0;
422
423 if (NULL == pAdapter)
424 {
425 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700426 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700427 ret = -ENODEV;
428 goto exit;
429 }
430
Jeff Johnsone7245742012-09-05 17:12:55 -0700431 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -0700432 {
433 ret = -EINVAL;
434 goto exit;
435 }
436
437 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
438 {
439 ret = -EFAULT;
440 goto exit;
441 }
442
443 command = kmalloc(priv_data.total_len, GFP_KERNEL);
444 if (!command)
445 {
446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700447 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700448 ret = -ENOMEM;
449 goto exit;
450 }
451
452 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
453 {
454 ret = -EFAULT;
455 goto exit;
456 }
457
458 if ((SIOCDEVPRIVATE + 1) == cmd)
459 {
460 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
461
462 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700463 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -0700464
465 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
466 {
467 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
468 sizeof(tSirMacAddr)))
469 {
470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700471 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700472 ret = -EFAULT;
473 }
474 }
Amar Singhal0974e402013-02-12 14:27:46 -0800475 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700476 {
Amar Singhal0974e402013-02-12 14:27:46 -0800477 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -0700478 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -0800479
Jeff Johnson295189b2012-06-20 16:38:30 -0700480 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800481
482 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -0700483 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -0700484 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -0800485 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -0700486 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -0800487 ret = hdd_setBand_helper(dev, ptr);
488 }
Jeff Johnson32d95a32012-09-10 13:15:23 -0700489 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
490 {
491 char *country_code;
492
493 country_code = command + 8;
494 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code,
495 pAdapter, pHddCtx->pvosContext);
496 if( 0 != ret )
497 {
498 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
499 "%s: SME Change Country code fail ret=%d\n",__func__, ret);
500
501 }
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700502 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800503#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
504 else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 )
505 {
506 tANI_U8 *value = command;
507 tANI_U8 countryCode[WNI_CFG_COUNTRY_CODE_LEN] = {0};
508 tANI_U8 revision = 0;
509 eHalStatus status = eHAL_STATUS_SUCCESS;
510 v_REGDOMAIN_t regId;
511
512 status = hdd_parse_countryrev(value, countryCode, &revision);
513 if (eHAL_STATUS_SUCCESS != status)
514 {
515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
516 "%s: Failed to parse country revision information", __func__);
517 ret = -EINVAL;
518 goto exit;
519 }
520
521 /* Validate country code */
522 status = sme_GetRegulatoryDomainForCountry(pHddCtx->hHal, countryCode, &regId);
523 if (eHAL_STATUS_SUCCESS != status)
524 {
525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
526 "%s: Invalid country code %s", __func__, countryCode);
527 ret = -EINVAL;
528 goto exit;
529 }
530
531 /* Validate revision */
532 if ((SME_KR_3 != revision) && (SME_KR_24 != revision) && (SME_KR_25 != revision))
533 {
534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
535 "%s: Invalid revision %d", __func__, revision);
536 ret = -EINVAL;
537 goto exit;
538 }
539
540 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode,
541 pAdapter, pHddCtx->pvosContext);
542 if (0 != ret)
543 {
544 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
545 "%s: SME Change Country code fail ret=%d", __func__, ret);
546 ret = -EINVAL;
547 goto exit;
548 }
549
550 if (0 == strncmp(countryCode, "KR", 2))
551 {
552 status = sme_ChangeCountryValidChannelListByRevision((tHalHandle)(pHddCtx->hHal),
553 revision);
554 if (eHAL_STATUS_SUCCESS != status)
555 {
556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
557 "%s: Failed to build valid channel list", __func__);
558 ret = -EINVAL;
559 goto exit;
560 }
561 }
562 }
563#endif
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700564 /*
565 command should be a string having format
566 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
567 */
Amar Singhal0974e402013-02-12 14:27:46 -0800568 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700569 {
Amar Singhal0974e402013-02-12 14:27:46 -0800570 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700571
572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700573 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -0700574
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -0800575 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -0700576 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800577 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
578 {
579 int suspend = 0;
580 tANI_U8 *ptr = (tANI_U8*)command + 15;
581
582 suspend = *ptr - '0';
583 hdd_set_wlan_suspend_mode(suspend);
584 }
Srinivas Girigowdade697412013-02-14 16:31:48 -0800585#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
586 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
587 {
588 tANI_U8 *value = command;
589 int rssi = 0;
590 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
591 eHalStatus status = eHAL_STATUS_SUCCESS;
592
593 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
594 value = value + 15;
595
596 sscanf(value, "%d", &rssi);
597 lookUpThreshold = abs(rssi);
598 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
599 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
600 {
601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
602 "Neighbor lookup threshold value %d is out of range"
603 " (Min: %d Max: %d)", lookUpThreshold,
604 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
605 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
606 ret = -EINVAL;
607 goto exit;
608 }
609
610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
611 "%s: Received Command to Set Roam trigger"
612 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
613
614 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
615 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
616 if (eHAL_STATUS_SUCCESS != status)
617 {
618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
619 "%s: Failed to set roam trigger, try again", __func__);
620 ret = -EPERM;
621 goto exit;
622 }
623
624 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
625 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
626 }
627 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
628 {
629 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
630 int rssi = (-1) * lookUpThreshold;
631 char extra[32];
632 tANI_U8 len = 0;
633
634 len = snprintf(extra, sizeof(extra), "%s %d", command, rssi);
635 if (copy_to_user(priv_data.buf, &extra, len + 1))
636 {
637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
638 "%s: failed to copy data to user buffer", __func__);
639 ret = -EFAULT;
640 goto exit;
641 }
642 }
643 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
644 {
645 tANI_U8 *value = command;
646 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
647 /* input refresh period is in terms of seconds */
648 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
649 value = value + 18;
650 /* Convert the value from ascii to integer */
651 ret = kstrtou16(value, 10, &neighborScanRefreshPeriod);
652 if (ret < 0)
653 {
654 /* If the input value is greater than max value of datatype, then also
655 kstrtou16 fails */
656 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
657 "%s: kstrtou16 failed ",
658 "Input value may be out of range[%d - %d]",
659 __func__,
660 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
661 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
662 ret = -EINVAL;
663 goto exit;
664 }
665
666 neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000;
667 if ((neighborScanRefreshPeriod < CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN) ||
668 (neighborScanRefreshPeriod > CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX))
669 {
670 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
671 "Neighbor scan results refresh period value %d is out of range"
672 " (Min: %d Max: %d)", neighborScanRefreshPeriod,
673 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
674 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
675 ret = -EINVAL;
676 goto exit;
677 }
678
679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
680 "%s: Received Command to Set roam scan period"
681 " (Neighbor Scan refresh period) = %d", __func__, neighborScanRefreshPeriod);
682
683 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborScanRefreshPeriod;
684 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
685 }
686 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
687 {
688 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
689 char extra[32];
690 tANI_U8 len = 0;
691
692 len = snprintf(extra, sizeof(extra), "%s %d", "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
693 /* Returned value is in units of seconds */
694 if (copy_to_user(priv_data.buf, &extra, len + 1))
695 {
696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
697 "%s: failed to copy data to user buffer", __func__);
698 ret = -EFAULT;
699 goto exit;
700 }
701 }
702#endif
703#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
704 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
705 {
706 tANI_U8 *value = command;
707 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
708
709 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
710 value = value + 13;
711 /* Convert the value from ascii to integer */
712 ret = kstrtou8(value, 10, &roamRssiDiff);
713 if (ret < 0)
714 {
715 /* If the input value is greater than max value of datatype, then also
716 kstrtou8 fails */
717 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
718 "%s: kstrtou8 failed range [%d - %d]", __func__,
719 CFG_ROAM_RSSI_DIFF_MIN,
720 CFG_ROAM_RSSI_DIFF_MAX);
721 ret = -EINVAL;
722 goto exit;
723 }
724
725 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
726 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
727 {
728 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
729 "Roam rssi diff value %d is out of range"
730 " (Min: %d Max: %d)", roamRssiDiff,
731 CFG_ROAM_RSSI_DIFF_MIN,
732 CFG_ROAM_RSSI_DIFF_MAX);
733 ret = -EINVAL;
734 goto exit;
735 }
736
737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
738 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
739
740 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
741 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
742 }
743 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
744 {
745 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
746 char extra[32];
747 tANI_U8 len = 0;
748
749 len = snprintf(extra, sizeof(extra), "%s %d", command, roamRssiDiff);
750 if (copy_to_user(priv_data.buf, &extra, len + 1))
751 {
752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
753 "%s: failed to copy data to user buffer", __func__);
754 ret = -EFAULT;
755 goto exit;
756 }
757 }
758#endif
759#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
760 else if (strncmp(command, "GETBAND", 7) == 0)
761 {
762 int band = -1;
763 char extra[32];
764 tANI_U8 len = 0;
765 hdd_getBand_helper(pHddCtx, &band);
766
767 len = snprintf(extra, sizeof(extra), "%s %d", command, band);
768 if (copy_to_user(priv_data.buf, &extra, len + 1))
769 {
770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
771 "%s: failed to copy data to user buffer", __func__);
772 ret = -EFAULT;
773 goto exit;
774 }
775 }
776 else if (strncmp(command, "GETCOUNTRYREV", 13) == 0)
777 {
778 tANI_U8 pBuf[WNI_CFG_COUNTRY_CODE_LEN];
779 tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN;
780 tANI_U8 revision = 0;
781 /* The format of the data copied to the user is GETCOUNTRYREV KR 25,
782 hence size of the array is country code + whitespace + 2 byte revision + ASCII NUL */
783 char extra[32] = {0};
784 tANI_U8 len = 0;
785
786 if (eHAL_STATUS_SUCCESS != sme_GetCountryCode( (tHalHandle)(pHddCtx->hHal), pBuf, &uBufLen ))
787 {
788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
789 "%s: failed to get country code", __func__);
790 ret = -EFAULT;
791 goto exit;
792 }
793 pBuf[uBufLen] = '\0';
794 sme_GetCountryRevision((tHalHandle)(pHddCtx->hHal), &revision);
795
796 if (0 == strncmp(pBuf, "KR", 2))
797 len = snprintf(extra, sizeof(extra), "%s %s %u", command, pBuf, revision);
798 else
799 len = snprintf(extra, sizeof(extra), "%s %s", command, pBuf);
800
801 if (copy_to_user(priv_data.buf, &extra, len + 1))
802 {
803 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
804 "%s: failed to copy data to user buffer", __func__);
805 ret = -EFAULT;
806 goto exit;
807 }
808 }
809 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
810 {
811 tANI_U8 *value = command;
812 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
813 tANI_U8 numChannels = 0;
814 eHalStatus status = eHAL_STATUS_SUCCESS;
815
816 status = hdd_parse_channellist(value, ChannelList, &numChannels);
817 if (eHAL_STATUS_SUCCESS != status)
818 {
819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
820 "%s: Failed to parse channel list information", __func__);
821 ret = -EINVAL;
822 goto exit;
823 }
824
825 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
826 {
827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
828 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
829 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
830 ret = -EINVAL;
831 goto exit;
832 }
833 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
834 numChannels);
835 if (eHAL_STATUS_SUCCESS != status)
836 {
837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
838 "%s: Failed to update channel list information", __func__);
839 ret = -EINVAL;
840 goto exit;
841 }
842 }
843 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
844 {
845 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
846 tANI_U8 numChannels = 0;
847 tANI_U8 len = 0, j = 0;
848 char extra[128] = {0};
849
850 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
851 ChannelList, &numChannels ))
852 {
853 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
854 "%s: failed to get roam scan channel list", __func__);
855 ret = -EFAULT;
856 goto exit;
857 }
858 /* output channel list is of the format
859 [Number of roam scan channels][Channel1][Channel2]... */
860 /* copy the number of channels in the 0th index */
861 len = snprintf(extra, sizeof(extra), "%s %d", command, numChannels);
862 for (j = 0; (j < numChannels); j++)
863 {
864 len += snprintf(extra + len, sizeof(extra) - len, " %d", ChannelList[j]);
865 }
866
867 if (copy_to_user(priv_data.buf, &extra, len + 1))
868 {
869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
870 "%s: failed to copy data to user buffer", __func__);
871 ret = -EFAULT;
872 goto exit;
873 }
874 }
875#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -0700876 else {
877 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
878 __func__, command);
879 }
880
Jeff Johnson295189b2012-06-20 16:38:30 -0700881 }
882exit:
883 if (command)
884 {
885 kfree(command);
886 }
887 return ret;
888}
889
Srinivas Girigowdade697412013-02-14 16:31:48 -0800890#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
891void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
892{
893 eCsrBand band = -1;
894 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
895 switch (band)
896 {
897 case eCSR_BAND_ALL:
898 *pBand = WLAN_HDD_UI_BAND_AUTO;
899 break;
900
901 case eCSR_BAND_24:
902 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
903 break;
904
905 case eCSR_BAND_5G:
906 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
907 break;
908
909 default:
910 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
911 *pBand = -1;
912 break;
913 }
914}
915
916/**---------------------------------------------------------------------------
917
918 \brief hdd_parse_countryrev() - HDD Parse country code revision
919
920 This function parses the country code revision passed in the format
921 SETCOUNTRYREV<space><Country code><space>revision
922
923 \param - pValue Pointer to input country code revision
924 \param - pCountryCode Pointer to local output array to record country code
925 \param - pRevision Pointer to store revision integer number
926
927 \return - 0 for success non-zero for failure
928
929 --------------------------------------------------------------------------*/
930VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 *pRevision)
931{
932 tANI_U8 *inPtr = pValue;
933 int tempInt;
934
935 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
936 /*no argument after the command*/
937 if (NULL == inPtr)
938 {
939 return -EINVAL;
940 }
941
942 /*no space after the command*/
943 else if (SPACE_ASCII_VALUE != *inPtr)
944 {
945 return -EINVAL;
946 }
947
948 /*removing empty spaces*/
949 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
950
951 /*no argument followed by spaces*/
952 if ('\0' == *inPtr)
953 {
954 return -EINVAL;
955 }
956
957 /*getting the first argument ie the country code */
958 sscanf(inPtr, "%s ", pCountryCode);
959
960 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
961 "Country code is : %s", pCountryCode);
962
963 /*inPtr pointing to the beginning of first space after country code */
964 inPtr = strpbrk( inPtr, " " );
965 /*no revision number after the country code argument */
966 if (NULL == inPtr)
967 {
968 return -EINVAL;
969 }
970
971 inPtr++;
972
973 /*removing empty space*/
974 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
975
976 /*no channel list after the number of channels argument and spaces*/
977 if (0 == strncmp(pCountryCode, "KR", 2))
978 {
979 if ('\0' == *inPtr)
980 {
981 return -EINVAL;
982 }
983
984 sscanf(inPtr, "%d", &tempInt);
985 *pRevision = tempInt;
986 }
987 else
988 {
989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
990 "Revision input is required only for Country KR");
991 return -EINVAL;
992 }
993 return VOS_STATUS_SUCCESS;
994}
995
996/**---------------------------------------------------------------------------
997
998 \brief hdd_parse_channellist() - HDD Parse channel list
999
1000 This function parses the channel list passed in the format
1001 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
1002
1003 \param - pValue Pointer to input channel list
1004 \param - ChannelList Pointer to local output array to record channel list
1005 \param - pNumChannels Pointer to number of roam scan channels
1006
1007 \return - 0 for success non-zero for failure
1008
1009 --------------------------------------------------------------------------*/
1010VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
1011{
1012 tANI_U8 *inPtr = pValue;
1013 int tempInt;
1014 int j = 0;
1015 int v = 0;
1016 char buf[32];
1017
1018 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
1019 /*no argument after the command*/
1020 if (NULL == inPtr)
1021 {
1022 return -EINVAL;
1023 }
1024
1025 /*no space after the command*/
1026 else if (SPACE_ASCII_VALUE != *inPtr)
1027 {
1028 return -EINVAL;
1029 }
1030
1031 /*removing empty spaces*/
1032 while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++;
1033
1034 /*no argument followed by spaces*/
1035 if ('\0' == *inPtr)
1036 {
1037 return -EINVAL;
1038 }
1039
1040 /*getting the first argument ie the number of channels*/
1041 sscanf(inPtr, "%s ", buf);
1042 v = kstrtos32(buf, 10, &tempInt);
1043 if ( v < 0) return -EINVAL;
1044
1045 *pNumChannels = tempInt;
1046
1047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1048 "Number of channels are: %d", *pNumChannels);
1049
1050 for (j = 0; j < (*pNumChannels); j++)
1051 {
1052 /*inPtr pointing to the beginning of first space after number of channels*/
1053 inPtr = strpbrk( inPtr, " " );
1054 /*no channel list after the number of channels argument*/
1055 if (NULL == inPtr)
1056 {
1057 return -EINVAL;
1058 }
1059
1060 /*removing empty space*/
1061 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
1062
1063 /*no channel list after the number of channels argument and spaces*/
1064 if ( '\0' == *inPtr )
1065 {
1066 return -EINVAL;
1067 }
1068
1069 sscanf(inPtr, "%s ", buf);
1070 v = kstrtos32(buf, 10, &tempInt);
1071 if ( v < 0) return -EINVAL;
1072 pChannelList[j] = tempInt;
1073
1074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1075 "Channel %d added to preferred channel list",
1076 pChannelList[j] );
1077 }
1078
1079 /* if the actual number of channels passed are more than
1080 pNumChannels then ignore the rest; take only pNumChannels */
1081 return VOS_STATUS_SUCCESS;
1082}
1083
1084#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001085/**---------------------------------------------------------------------------
1086
1087 \brief hdd_open() - HDD Open function
1088
1089 This is called in response to ifconfig up
1090
1091 \param - dev Pointer to net_device structure
1092
1093 \return - 0 for success non-zero for failure
1094
1095 --------------------------------------------------------------------------*/
1096int hdd_open (struct net_device *dev)
1097{
1098 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1099 hdd_context_t *pHddCtx;
1100 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1101 VOS_STATUS status;
1102 v_BOOL_t in_standby = TRUE;
1103
1104 if (NULL == pAdapter)
1105 {
1106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001107 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001108 return -ENODEV;
1109 }
1110
1111 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1112 if (NULL == pHddCtx)
1113 {
1114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001115 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001116 return -ENODEV;
1117 }
1118
1119 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1120 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1121 {
1122 if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1123 {
1124 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of "
1125 "standby", __func__, pAdapter->device_mode);
1126 in_standby = FALSE;
1127 break;
1128 }
1129 else
1130 {
1131 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1132 pAdapterNode = pNext;
1133 }
1134 }
1135
1136 if (TRUE == in_standby)
1137 {
1138 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
1139 {
1140 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
1141 "wlan out of power save", __func__);
1142 return -EINVAL;
1143 }
1144 }
1145
1146 pAdapter->event_flags |= DEVICE_IFACE_OPENED;
1147 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
1148 {
1149 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001150 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001151 /* Enable TX queues only when we are connected */
1152 netif_tx_start_all_queues(dev);
1153 }
1154
1155 return 0;
1156}
1157
1158int hdd_mon_open (struct net_device *dev)
1159{
1160 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1161
1162 if(pAdapter == NULL) {
1163 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001164 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08001165 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07001166 }
1167
1168 netif_start_queue(dev);
1169
1170 return 0;
1171}
1172/**---------------------------------------------------------------------------
1173
1174 \brief hdd_stop() - HDD stop function
1175
1176 This is called in response to ifconfig down
1177
1178 \param - dev Pointer to net_device structure
1179
1180 \return - 0 for success non-zero for failure
1181
1182 --------------------------------------------------------------------------*/
1183
1184int hdd_stop (struct net_device *dev)
1185{
1186 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1187 hdd_context_t *pHddCtx;
1188 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
1189 VOS_STATUS status;
1190 v_BOOL_t enter_standby = TRUE;
1191
1192 ENTER();
1193
1194 if (NULL == pAdapter)
1195 {
1196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001197 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001198 return -ENODEV;
1199 }
1200
1201 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1202 if (NULL == pHddCtx)
1203 {
1204 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001205 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001206 return -ENODEV;
1207 }
1208
1209 pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED);
1210 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
1211 netif_tx_disable(pAdapter->dev);
1212 netif_carrier_off(pAdapter->dev);
1213
1214
1215 /* SoftAP ifaces should never go in power save mode
1216 making sure same here. */
1217 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
1218 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
1219#ifdef WLAN_FEATURE_P2P
1220 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
1221#endif
1222 )
1223 {
1224 /* SoftAP mode, so return from here */
1225 EXIT();
1226 return 0;
1227 }
1228
1229 /* Find if any iface is up then
1230 if any iface is up then can't put device to sleep/ power save mode. */
1231 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
1232 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
1233 {
1234 if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED)
1235 {
1236 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
1237 "put device to sleep", __func__, pAdapter->device_mode);
1238 enter_standby = FALSE;
1239 break;
1240 }
1241 else
1242 {
1243 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
1244 pAdapterNode = pNext;
1245 }
1246 }
1247
1248 if (TRUE == enter_standby)
1249 {
1250 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
1251 "entering standby", __func__);
1252 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
1253 {
1254 /*log and return success*/
1255 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
1256 "wlan in power save", __func__);
1257 }
1258 }
1259
1260 EXIT();
1261 return 0;
1262}
1263
1264/**---------------------------------------------------------------------------
1265
1266 \brief hdd_uninit() - HDD uninit function
1267
1268 This is called during the netdev unregister to uninitialize all data
1269associated with the device
1270
1271 \param - dev Pointer to net_device structure
1272
1273 \return - void
1274
1275 --------------------------------------------------------------------------*/
1276static void hdd_uninit (struct net_device *dev)
1277{
1278 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1279
1280 ENTER();
1281
1282 do
1283 {
1284 if (NULL == pAdapter)
1285 {
1286 hddLog(VOS_TRACE_LEVEL_FATAL,
1287 "%s: NULL pAdapter", __func__);
1288 break;
1289 }
1290
1291 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1292 {
1293 hddLog(VOS_TRACE_LEVEL_FATAL,
1294 "%s: Invalid magic", __func__);
1295 break;
1296 }
1297
1298 if (NULL == pAdapter->pHddCtx)
1299 {
1300 hddLog(VOS_TRACE_LEVEL_FATAL,
1301 "%s: NULL pHddCtx", __func__);
1302 break;
1303 }
1304
1305 if (dev != pAdapter->dev)
1306 {
1307 hddLog(VOS_TRACE_LEVEL_FATAL,
1308 "%s: Invalid device reference", __func__);
1309 /* we haven't validated all cases so let this go for now */
1310 }
1311
1312 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
1313
1314 /* after uninit our adapter structure will no longer be valid */
1315 pAdapter->dev = NULL;
1316 pAdapter->magic = 0;
1317 } while (0);
1318
1319 EXIT();
1320}
1321
1322/**---------------------------------------------------------------------------
1323
1324 \brief hdd_release_firmware() -
1325
1326 This function calls the release firmware API to free the firmware buffer.
1327
1328 \param - pFileName Pointer to the File Name.
1329 pCtx - Pointer to the adapter .
1330
1331
1332 \return - 0 for success, non zero for failure
1333
1334 --------------------------------------------------------------------------*/
1335
1336VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
1337{
1338 VOS_STATUS status = VOS_STATUS_SUCCESS;
1339 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1340 ENTER();
1341
1342
1343 if (!strcmp(WLAN_FW_FILE, pFileName)) {
1344
1345 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
1346
1347 if(pHddCtx->fw) {
1348 release_firmware(pHddCtx->fw);
1349 pHddCtx->fw = NULL;
1350 }
1351 else
1352 status = VOS_STATUS_E_FAILURE;
1353 }
1354 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
1355 if(pHddCtx->nv) {
1356 release_firmware(pHddCtx->nv);
1357 pHddCtx->nv = NULL;
1358 }
1359 else
1360 status = VOS_STATUS_E_FAILURE;
1361
1362 }
1363
1364 EXIT();
1365 return status;
1366}
1367
1368/**---------------------------------------------------------------------------
1369
1370 \brief hdd_request_firmware() -
1371
1372 This function reads the firmware file using the request firmware
1373 API and returns the the firmware data and the firmware file size.
1374
1375 \param - pfileName - Pointer to the file name.
1376 - pCtx - Pointer to the adapter .
1377 - ppfw_data - Pointer to the pointer of the firmware data.
1378 - pSize - Pointer to the file size.
1379
1380 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
1381
1382 --------------------------------------------------------------------------*/
1383
1384
1385VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
1386{
1387 int status;
1388 VOS_STATUS retval = VOS_STATUS_SUCCESS;
1389 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1390 ENTER();
1391
1392 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
1393
1394 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
1395
1396 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1397 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
1398 __func__, pfileName);
1399 retval = VOS_STATUS_E_FAILURE;
1400 }
1401
1402 else {
1403 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
1404 *pSize = pHddCtx->fw->size;
1405 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
1406 __func__, *pSize);
1407 }
1408 }
1409 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
1410
1411 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
1412
1413 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
1414 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
1415 __func__, pfileName);
1416 retval = VOS_STATUS_E_FAILURE;
1417 }
1418
1419 else {
1420 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
1421 *pSize = pHddCtx->nv->size;
1422 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
1423 __func__, *pSize);
1424 }
1425 }
1426
1427 EXIT();
1428 return retval;
1429}
1430/**---------------------------------------------------------------------------
1431 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
1432
1433 This is the function invoked by SME to inform the result of a full power
1434 request issued by HDD
1435
1436 \param - callbackcontext - Pointer to cookie
1437 status - result of request
1438
1439 \return - None
1440
1441--------------------------------------------------------------------------*/
1442void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
1443{
1444 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
1445
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001446 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07001447 if(&pHddCtx->full_pwr_comp_var)
1448 {
1449 complete(&pHddCtx->full_pwr_comp_var);
1450 }
1451}
1452
1453/**---------------------------------------------------------------------------
1454
1455 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
1456
1457 This is the function invoked by SME to inform the result of BMPS
1458 request issued by HDD
1459
1460 \param - callbackcontext - Pointer to cookie
1461 status - result of request
1462
1463 \return - None
1464
1465--------------------------------------------------------------------------*/
1466void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
1467{
1468
1469 struct completion *completion_var = (struct completion*) callbackContext;
1470
1471 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
1472 if(completion_var != NULL)
1473 {
1474 complete(completion_var);
1475 }
1476}
1477
1478/**---------------------------------------------------------------------------
1479
1480 \brief hdd_get_cfg_file_size() -
1481
1482 This function reads the configuration file using the request firmware
1483 API and returns the configuration file size.
1484
1485 \param - pCtx - Pointer to the adapter .
1486 - pFileName - Pointer to the file name.
1487 - pBufSize - Pointer to the buffer size.
1488
1489 \return - 0 for success, non zero for failure
1490
1491 --------------------------------------------------------------------------*/
1492
1493VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
1494{
1495 int status;
1496 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1497
1498 ENTER();
1499
1500 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1501
1502 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1503 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1504 status = VOS_STATUS_E_FAILURE;
1505 }
1506 else {
1507 *pBufSize = pHddCtx->fw->size;
1508 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
1509 release_firmware(pHddCtx->fw);
1510 pHddCtx->fw = NULL;
1511 }
1512
1513 EXIT();
1514 return VOS_STATUS_SUCCESS;
1515}
1516
1517/**---------------------------------------------------------------------------
1518
1519 \brief hdd_read_cfg_file() -
1520
1521 This function reads the configuration file using the request firmware
1522 API and returns the cfg data and the buffer size of the configuration file.
1523
1524 \param - pCtx - Pointer to the adapter .
1525 - pFileName - Pointer to the file name.
1526 - pBuffer - Pointer to the data buffer.
1527 - pBufSize - Pointer to the buffer size.
1528
1529 \return - 0 for success, non zero for failure
1530
1531 --------------------------------------------------------------------------*/
1532
1533VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
1534 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
1535{
1536 int status;
1537 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
1538
1539 ENTER();
1540
1541 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
1542
1543 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
1544 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
1545 return VOS_STATUS_E_FAILURE;
1546 }
1547 else {
1548 if(*pBufSize != pHddCtx->fw->size) {
1549 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
1550 "file size", __func__);
1551 release_firmware(pHddCtx->fw);
1552 pHddCtx->fw = NULL;
1553 return VOS_STATUS_E_FAILURE;
1554 }
1555 else {
1556 if(pBuffer) {
1557 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
1558 }
1559 release_firmware(pHddCtx->fw);
1560 pHddCtx->fw = NULL;
1561 }
1562 }
1563
1564 EXIT();
1565
1566 return VOS_STATUS_SUCCESS;
1567}
1568
1569/**---------------------------------------------------------------------------
1570
1571 \brief hdd_set_mac_addr_cb() -
1572
1573 This function is the call back function for setting the station
1574 mac adrress called by ccm module to indicate the
1575 success/failure result.
1576
1577 \param - hHal - Pointer to the hal module.
1578 - result - returns the result of the set mac address.
1579
1580 \return - void
1581
1582 --------------------------------------------------------------------------*/
1583#ifndef FEATURE_WLAN_INTEGRATED_SOC
1584static void hdd_set_mac_addr_cb( tHalHandle hHal, tANI_S32 result )
1585{
1586 // ignore the STA_ID response for now.
1587
1588 VOS_ASSERT( CCM_IS_RESULT_SUCCESS( result ) );
1589}
1590#endif
1591
1592
1593/**---------------------------------------------------------------------------
1594
1595 \brief hdd_set_mac_address() -
1596
1597 This function sets the user specified mac address using
1598 the command ifconfig wlanX hw ether <mac adress>.
1599
1600 \param - dev - Pointer to the net device.
1601 - addr - Pointer to the sockaddr.
1602 \return - 0 for success, non zero for failure
1603
1604 --------------------------------------------------------------------------*/
1605
1606static int hdd_set_mac_address(struct net_device *dev, void *addr)
1607{
1608 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1609 struct sockaddr *psta_mac_addr = addr;
1610 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1611
1612 ENTER();
1613
1614 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
1615
1616#ifdef HDD_SESSIONIZE
1617 // set the MAC address though the STA ID CFG.
1618 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
1619 (v_U8_t *)&pAdapter->macAddressCurrent,
1620 sizeof( pAdapter->macAddressCurrent ),
1621 hdd_set_mac_addr_cb, VOS_FALSE );
1622#endif
1623
1624 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
1625
1626 EXIT();
1627 return halStatus;
1628}
1629
1630tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
1631{
1632 int i;
1633 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1634 {
1635 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
1636 break;
1637 }
1638
1639 if( VOS_MAX_CONCURRENCY_PERSONA == i)
1640 return NULL;
1641
1642 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
1643 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
1644}
1645
1646void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
1647{
1648 int i;
1649 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
1650 {
1651 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
1652 {
1653 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
1654 break;
1655 }
1656 }
1657 return;
1658}
1659
1660#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1661 static struct net_device_ops wlan_drv_ops = {
1662 .ndo_open = hdd_open,
1663 .ndo_stop = hdd_stop,
1664 .ndo_uninit = hdd_uninit,
1665 .ndo_start_xmit = hdd_hard_start_xmit,
1666 .ndo_tx_timeout = hdd_tx_timeout,
1667 .ndo_get_stats = hdd_stats,
1668 .ndo_do_ioctl = hdd_ioctl,
1669 .ndo_set_mac_address = hdd_set_mac_address,
1670 .ndo_select_queue = hdd_select_queue,
1671#ifdef WLAN_FEATURE_PACKET_FILTERING
1672#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
1673 .ndo_set_rx_mode = hdd_set_multicast_list,
1674#else
1675 .ndo_set_multicast_list = hdd_set_multicast_list,
1676#endif //LINUX_VERSION_CODE
1677#endif
1678 };
1679#ifdef CONFIG_CFG80211
1680 static struct net_device_ops wlan_mon_drv_ops = {
1681 .ndo_open = hdd_mon_open,
1682 .ndo_stop = hdd_stop,
1683 .ndo_uninit = hdd_uninit,
1684 .ndo_start_xmit = hdd_mon_hard_start_xmit,
1685 .ndo_tx_timeout = hdd_tx_timeout,
1686 .ndo_get_stats = hdd_stats,
1687 .ndo_do_ioctl = hdd_ioctl,
1688 .ndo_set_mac_address = hdd_set_mac_address,
1689 };
1690#endif
1691
1692#endif
1693
1694void hdd_set_station_ops( struct net_device *pWlanDev )
1695{
1696#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1697 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
1698 pWlanDev->netdev_ops = &wlan_drv_ops;
1699#else
1700 pWlanDev->open = hdd_open;
1701 pWlanDev->stop = hdd_stop;
1702 pWlanDev->uninit = hdd_uninit;
1703 pWlanDev->hard_start_xmit = NULL;
1704 pWlanDev->tx_timeout = hdd_tx_timeout;
1705 pWlanDev->get_stats = hdd_stats;
1706 pWlanDev->do_ioctl = hdd_ioctl;
1707 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
1708 pWlanDev->set_mac_address = hdd_set_mac_address;
1709#endif
1710}
1711
Jeff Johnsoneed415b2013-01-18 16:11:20 -08001712static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07001713{
1714 struct net_device *pWlanDev = NULL;
1715 hdd_adapter_t *pAdapter = NULL;
1716#ifdef CONFIG_CFG80211
1717 /*
1718 * cfg80211 initialization and registration....
1719 */
1720 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
1721
1722#else
1723 //Allocate the net_device and private data (station ctx)
1724 pWlanDev = alloc_etherdev_mq(sizeof( hdd_adapter_t ), NUM_TX_QUEUES);
1725
1726#endif
1727
1728 if(pWlanDev != NULL)
1729 {
1730
1731 //Save the pointer to the net_device in the HDD adapter
1732 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
1733
1734#ifndef CONFIG_CFG80211
1735 //Init the net_device structure
1736 ether_setup(pWlanDev);
1737#endif
1738
1739 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
1740
1741 pAdapter->dev = pWlanDev;
1742 pAdapter->pHddCtx = pHddCtx;
1743 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
1744
1745 init_completion(&pAdapter->session_open_comp_var);
1746 init_completion(&pAdapter->session_close_comp_var);
1747 init_completion(&pAdapter->disconnect_comp_var);
1748 init_completion(&pAdapter->linkup_event_var);
1749 init_completion(&pAdapter->cancel_rem_on_chan_var);
1750 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07001751#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
1752 init_completion(&pAdapter->offchannel_tx_event);
1753#endif
1754#ifdef CONFIG_CFG80211
1755 init_completion(&pAdapter->tx_action_cnf_event);
1756#endif
Hoonki Lee11f7dda2013-02-14 16:55:44 -08001757#ifdef FEATURE_WLAN_TDLS
1758 init_completion(&pAdapter->tdls_add_station_comp);
1759#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07001760 init_completion(&pHddCtx->mc_sus_event_var);
1761 init_completion(&pHddCtx->tx_sus_event_var);
1762
Jeff Johnson295189b2012-06-20 16:38:30 -07001763 pAdapter->isLinkUpSvcNeeded = FALSE;
1764 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
1765 //Init the net_device structure
1766 strlcpy(pWlanDev->name, name, IFNAMSIZ);
1767
1768 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
1769 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
1770 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
1771 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
1772
1773 hdd_set_station_ops( pAdapter->dev );
1774
1775 pWlanDev->destructor = free_netdev;
1776#ifdef CONFIG_CFG80211
1777 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
1778 pAdapter->wdev.wiphy = pHddCtx->wiphy;
1779 pAdapter->wdev.netdev = pWlanDev;
1780#endif
1781 /* set pWlanDev's parent to underlying device */
1782 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
1783 }
1784
1785 return pAdapter;
1786}
1787
1788VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
1789{
1790 struct net_device *pWlanDev = pAdapter->dev;
1791 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1792 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1793 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1794
1795 if( rtnl_lock_held )
1796 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08001797 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07001798 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
1799 {
1800 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
1801 return VOS_STATUS_E_FAILURE;
1802 }
1803 }
1804 if (register_netdevice(pWlanDev))
1805 {
1806 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
1807 return VOS_STATUS_E_FAILURE;
1808 }
1809 }
1810 else
1811 {
1812 if(register_netdev(pWlanDev))
1813 {
1814 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
1815 return VOS_STATUS_E_FAILURE;
1816 }
1817 }
1818 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
1819
1820 return VOS_STATUS_SUCCESS;
1821}
1822
1823eHalStatus hdd_smeCloseSessionCallback(void *pContext)
1824{
1825 if(pContext != NULL)
1826 {
1827 clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags);
1828
1829 /* need to make sure all of our scheduled work has completed.
1830 * This callback is called from MC thread context, so it is safe to
1831 * to call below flush workqueue API from here.
1832 */
1833 flush_scheduled_work();
1834 complete(&((hdd_adapter_t*)pContext)->session_close_comp_var);
1835 }
1836 return eHAL_STATUS_SUCCESS;
1837}
1838
1839VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
1840{
1841 struct net_device *pWlanDev = pAdapter->dev;
1842 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
1843 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
1844 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
1845 VOS_STATUS status = VOS_STATUS_E_FAILURE;
1846 int rc = 0;
1847
1848 INIT_COMPLETION(pAdapter->session_open_comp_var);
1849 //Open a SME session for future operation
1850 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
1851 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId );
1852 if ( !HAL_STATUS_SUCCESS( halStatus ) )
1853 {
1854 hddLog(VOS_TRACE_LEVEL_FATAL,
1855 "sme_OpenSession() failed with status code %08d [x%08lx]",
1856 halStatus, halStatus );
1857 status = VOS_STATUS_E_FAILURE;
1858 goto error_sme_open;
1859 }
1860
1861 //Block on a completion variable. Can't wait forever though.
1862 rc = wait_for_completion_interruptible_timeout(
1863 &pAdapter->session_open_comp_var,
1864 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1865 if (!rc)
1866 {
1867 hddLog(VOS_TRACE_LEVEL_FATAL,
1868 "Session is not opened within timeout period code %08d", rc );
1869 status = VOS_STATUS_E_FAILURE;
1870 goto error_sme_open;
1871 }
1872
1873 // Register wireless extensions
1874 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
1875 {
1876 hddLog(VOS_TRACE_LEVEL_FATAL,
1877 "hdd_register_wext() failed with status code %08d [x%08lx]",
1878 halStatus, halStatus );
1879 status = VOS_STATUS_E_FAILURE;
1880 goto error_register_wext;
1881 }
1882 //Safe to register the hard_start_xmit function again
1883#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
1884 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
1885#else
1886 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
1887#endif
1888
1889 //Set the Connection State to Not Connected
1890 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
1891
1892 //Set the default operation channel
1893 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
1894
1895 /* Make the default Auth Type as OPEN*/
1896 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
1897
1898 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
1899 {
1900 hddLog(VOS_TRACE_LEVEL_FATAL,
1901 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
1902 status, status );
1903 goto error_init_txrx;
1904 }
1905
1906 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1907
1908 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
1909 {
1910 hddLog(VOS_TRACE_LEVEL_FATAL,
1911 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
1912 status, status );
1913 goto error_wmm_init;
1914 }
1915
1916 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1917
1918 return VOS_STATUS_SUCCESS;
1919
1920error_wmm_init:
1921 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1922 hdd_deinit_tx_rx(pAdapter);
1923error_init_txrx:
1924 hdd_UnregisterWext(pWlanDev);
1925error_register_wext:
1926 if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
1927 {
1928 INIT_COMPLETION(pAdapter->session_close_comp_var);
1929 if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal,
1930 pAdapter->sessionId,
1931 hdd_smeCloseSessionCallback, pAdapter ) )
1932 {
1933 //Block on a completion variable. Can't wait forever though.
1934 wait_for_completion_interruptible_timeout(
1935 &pAdapter->session_close_comp_var,
1936 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
1937 }
1938}
1939error_sme_open:
1940 return status;
1941}
1942
Jeff Johnson295189b2012-06-20 16:38:30 -07001943#ifdef CONFIG_CFG80211
1944void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1945{
1946 hdd_cfg80211_state_t *cfgState;
1947
1948 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
1949
1950 if( NULL != cfgState->buf )
1951 {
1952 int rc;
1953 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
1954 rc = wait_for_completion_interruptible_timeout(
1955 &pAdapter->tx_action_cnf_event,
1956 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
1957 if(!rc)
1958 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08001959 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07001960 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
1961 }
1962 }
1963 return;
1964}
1965#endif
1966
1967void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
1968{
1969 ENTER();
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 {
1976 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
1977 {
1978 hdd_deinit_tx_rx( pAdapter );
1979 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
1980 }
1981
1982 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
1983 {
1984 hdd_wmm_adapter_close( pAdapter );
1985 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
1986 }
1987
1988#ifdef CONFIG_CFG80211
1989 hdd_cleanup_actionframe(pHddCtx, pAdapter);
1990#endif
1991
1992 break;
1993 }
1994
1995 case WLAN_HDD_SOFTAP:
1996 case WLAN_HDD_P2P_GO:
1997#ifdef WLAN_SOFTAP_FEATURE
1998 {
1999#ifdef CONFIG_CFG80211
2000 hdd_cleanup_actionframe(pHddCtx, pAdapter);
2001#endif
2002
2003 hdd_unregister_hostapd(pAdapter);
2004 hdd_set_conparam( 0 );
2005#ifdef CONFIG_CFG80211
2006 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
2007#endif
2008 break;
2009 }
2010
2011 case WLAN_HDD_MONITOR:
2012 {
2013#ifdef CONFIG_CFG80211
2014 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
2015#endif
2016 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
2017 {
2018 hdd_deinit_tx_rx( pAdapter );
2019 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2020 }
2021#ifdef CONFIG_CFG80211
2022 if(NULL != pAdapterforTx)
2023 {
2024 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
2025 }
2026#endif
2027#endif //WLAN_SOFTAP_FEATURE
2028 break;
2029 }
2030
2031
2032 default:
2033 break;
2034 }
2035
2036 EXIT();
2037}
2038
2039void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
2040{
2041 struct net_device *pWlanDev = pAdapter->dev;
2042
2043 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
2044 if( rtnl_held )
2045 {
2046 unregister_netdevice(pWlanDev);
2047 }
2048 else
2049 {
2050 unregister_netdev(pWlanDev);
2051 }
2052 // note that the pAdapter is no longer valid at this point
2053 // since the memory has been reclaimed
2054 }
2055
2056}
2057
2058VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2059{
2060 VOS_STATUS status = VOS_STATUS_SUCCESS;
2061
2062 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2063 {
2064 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2065 }
2066
2067 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2068 {
2069 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2070 }
2071
2072 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2073 {
2074 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2075 }
2076
2077 return status;
2078}
2079
2080VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2081{
2082 hdd_adapter_t *pAdapter = NULL;
2083 eHalStatus halStatus;
2084 VOS_STATUS status = VOS_STATUS_E_INVAL;
2085 v_BOOL_t disableBmps = FALSE;
2086 v_BOOL_t disableImps = FALSE;
2087
2088 switch(session_type)
2089 {
2090 case WLAN_HDD_INFRA_STATION:
2091 case WLAN_HDD_SOFTAP:
2092#ifdef WLAN_FEATURE_P2P
2093 case WLAN_HDD_P2P_CLIENT:
2094 case WLAN_HDD_P2P_GO:
2095#endif
2096 //Exit BMPS -> Is Sta/P2P Client is already connected
2097 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2098 if((NULL != pAdapter)&&
2099 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2100 {
2101 disableBmps = TRUE;
2102 }
2103
2104 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2105 if((NULL != pAdapter)&&
2106 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2107 {
2108 disableBmps = TRUE;
2109 }
2110
2111 //Exit both Bmps and Imps incase of Go/SAP Mode
2112 if((WLAN_HDD_SOFTAP == session_type) ||
2113 (WLAN_HDD_P2P_GO == session_type))
2114 {
2115 disableBmps = TRUE;
2116 disableImps = TRUE;
2117 }
2118
2119 if(TRUE == disableImps)
2120 {
2121 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2122 {
2123 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2124 }
2125 }
2126
2127 if(TRUE == disableBmps)
2128 {
2129 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2130 {
2131 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2132
2133 if(eHAL_STATUS_SUCCESS != halStatus)
2134 {
2135 status = VOS_STATUS_E_FAILURE;
2136 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2137 VOS_ASSERT(0);
2138 return status;
2139 }
2140 }
2141
2142 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2143 {
2144 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2145
2146 if(eHAL_STATUS_SUCCESS != halStatus)
2147 {
2148 status = VOS_STATUS_E_FAILURE;
2149 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2150 VOS_ASSERT(0);
2151 return status;
2152 }
2153 }
2154 }
2155
2156 if((TRUE == disableBmps) ||
2157 (TRUE == disableImps))
2158 {
2159 /* Now, get the chip into Full Power now */
2160 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2161 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2162 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2163
2164 if(halStatus != eHAL_STATUS_SUCCESS)
2165 {
2166 if(halStatus == eHAL_STATUS_PMC_PENDING)
2167 {
2168 //Block on a completion variable. Can't wait forever though
2169 wait_for_completion_interruptible_timeout(
2170 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2171 }
2172 else
2173 {
2174 status = VOS_STATUS_E_FAILURE;
2175 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2176 VOS_ASSERT(0);
2177 return status;
2178 }
2179 }
2180
2181 status = VOS_STATUS_SUCCESS;
2182 }
2183
2184 break;
2185 }
2186 return status;
2187}
2188
2189hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002190 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002191 tANI_U8 rtnl_held )
2192{
2193 hdd_adapter_t *pAdapter = NULL;
2194 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2195 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2196 VOS_STATUS exitbmpsStatus;
2197
2198 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2199
2200 //Disable BMPS incase of Concurrency
2201 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2202
2203 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2204 {
2205 //Fail to Exit BMPS
2206 VOS_ASSERT(0);
2207 return NULL;
2208 }
2209
2210 switch(session_type)
2211 {
2212 case WLAN_HDD_INFRA_STATION:
2213#ifdef WLAN_FEATURE_P2P
2214 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002215 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002216#endif
2217 {
2218 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2219
2220 if( NULL == pAdapter )
2221 return NULL;
2222
2223#ifdef CONFIG_CFG80211
Jeff Johnsone7245742012-09-05 17:12:55 -07002224 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2225 NL80211_IFTYPE_P2P_CLIENT:
2226 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002227#endif
2228
Jeff Johnson295189b2012-06-20 16:38:30 -07002229 pAdapter->device_mode = session_type;
2230
2231 status = hdd_init_station_mode( pAdapter );
2232 if( VOS_STATUS_SUCCESS != status )
2233 goto err_free_netdev;
2234
2235 status = hdd_register_interface( pAdapter, rtnl_held );
2236 if( VOS_STATUS_SUCCESS != status )
2237 {
2238 hdd_deinit_adapter(pHddCtx, pAdapter);
2239 goto err_free_netdev;
2240 }
2241 //Stop the Interface TX queue.
2242 netif_tx_disable(pAdapter->dev);
2243 //netif_tx_disable(pWlanDev);
2244 netif_carrier_off(pAdapter->dev);
2245
2246 break;
2247 }
2248
2249#ifdef WLAN_FEATURE_P2P
2250 case WLAN_HDD_P2P_GO:
2251#endif
2252 case WLAN_HDD_SOFTAP:
2253 {
2254 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2255 if( NULL == pAdapter )
2256 return NULL;
2257
2258#ifdef CONFIG_CFG80211
2259 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2260 NL80211_IFTYPE_AP:
2261 NL80211_IFTYPE_P2P_GO;
2262#endif
2263 pAdapter->device_mode = session_type;
2264
2265 status = hdd_init_ap_mode(pAdapter);
2266 if( VOS_STATUS_SUCCESS != status )
2267 goto err_free_netdev;
2268
2269 status = hdd_register_hostapd( pAdapter, rtnl_held );
2270 if( VOS_STATUS_SUCCESS != status )
2271 {
2272 hdd_deinit_adapter(pHddCtx, pAdapter);
2273 goto err_free_netdev;
2274 }
2275
2276 netif_tx_disable(pAdapter->dev);
2277 netif_carrier_off(pAdapter->dev);
2278
2279 hdd_set_conparam( 1 );
2280 break;
2281 }
2282 case WLAN_HDD_MONITOR:
2283 {
2284#ifdef CONFIG_CFG80211
2285 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2286 if( NULL == pAdapter )
2287 return NULL;
2288
2289 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2290 pAdapter->device_mode = session_type;
2291 status = hdd_register_interface( pAdapter, rtnl_held );
2292#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2293 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2294#else
2295 pAdapter->dev->open = hdd_mon_open;
2296 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2297#endif
2298 hdd_init_tx_rx( pAdapter );
2299 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2300 //Set adapter to be used for data tx. It will use either GO or softap.
2301 pAdapter->sessionCtx.monitor.pAdapterForTx =
2302 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
2303#ifdef WLAN_FEATURE_P2P
2304 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2305 {
2306 pAdapter->sessionCtx.monitor.pAdapterForTx =
2307 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2308 }
2309#endif
2310 /* This workqueue will be used to transmit management packet over
2311 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002312 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2313 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2314 return NULL;
2315 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002316
Jeff Johnson295189b2012-06-20 16:38:30 -07002317 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2318 hdd_mon_tx_work_queue);
2319#endif
2320 }
2321 break;
2322#ifdef ANI_MANF_DIAG
2323 case WLAN_HDD_FTM:
2324 {
2325 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2326
2327 if( NULL == pAdapter )
2328 return NULL;
2329 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2330 * message while loading driver in FTM mode. */
2331 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2332 pAdapter->device_mode = session_type;
2333 status = hdd_register_interface( pAdapter, rtnl_held );
2334 }
2335 break;
2336#endif
2337 default:
2338 {
2339 VOS_ASSERT(0);
2340 return NULL;
2341 }
2342 }
2343
2344
2345 if( VOS_STATUS_SUCCESS == status )
2346 {
2347 //Add it to the hdd's session list.
2348 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2349 if( NULL == pHddAdapterNode )
2350 {
2351 status = VOS_STATUS_E_NOMEM;
2352 }
2353 else
2354 {
2355 pHddAdapterNode->pAdapter = pAdapter;
2356 status = hdd_add_adapter_back ( pHddCtx,
2357 pHddAdapterNode );
2358 }
2359 }
2360
2361 if( VOS_STATUS_SUCCESS != status )
2362 {
2363 if( NULL != pAdapter )
2364 {
2365 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2366 pAdapter = NULL;
2367 }
2368 if( NULL != pHddAdapterNode )
2369 {
2370 vos_mem_free( pHddAdapterNode );
2371 }
2372
2373 goto resume_bmps;
2374 }
2375
2376 if(VOS_STATUS_SUCCESS == status)
2377 {
2378 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2379
2380#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
2381 /* If there are concurrent session enable SW frame translation
2382 * for all registered STA
2383 * This is not required in case of PRIMA as HW frame translation
2384 * is disabled in PRIMA*/
2385 if (vos_concurrent_sessions_running())
2386 {
2387 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, TRUE);
2388 }
2389#endif
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002390 //Initialize the WoWL service
2391 if(!hdd_init_wowl(pAdapter))
2392 {
2393 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2394 goto err_free_netdev;
2395 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002396 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002397 return pAdapter;
2398
2399err_free_netdev:
2400 free_netdev(pAdapter->dev);
2401 wlan_hdd_release_intf_addr( pHddCtx,
2402 pAdapter->macAddressCurrent.bytes );
2403
2404resume_bmps:
2405 //If bmps disabled enable it
2406 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2407 {
2408 hdd_enable_bmps_imps(pHddCtx);
2409 }
2410 return NULL;
2411}
2412
2413VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2414 tANI_U8 rtnl_held )
2415{
2416 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2417 VOS_STATUS status;
2418
2419 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2420 if( VOS_STATUS_SUCCESS != status )
2421 return status;
2422
2423 while ( pCurrent->pAdapter != pAdapter )
2424 {
2425 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2426 if( VOS_STATUS_SUCCESS != status )
2427 break;
2428
2429 pCurrent = pNext;
2430 }
2431 pAdapterNode = pCurrent;
2432 if( VOS_STATUS_SUCCESS == status )
2433 {
2434 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2435 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2436 hdd_remove_adapter( pHddCtx, pAdapterNode );
2437 vos_mem_free( pAdapterNode );
2438
2439#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
2440 /* If there is no concurrent session disable SW frame translation
2441 * for all registered STA */
2442 /* This is not required in case of PRIMA as HW frame translation
2443 * is disabled in PRIMA*/
2444 if (!vos_concurrent_sessions_running())
2445 {
2446 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, FALSE);
2447 }
2448#endif
2449
2450 /* If there is a single session of STA/P2P client, re-enable BMPS */
2451 if ((!vos_concurrent_sessions_running()) &&
2452 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2453 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2454 {
2455 hdd_enable_bmps_imps(pHddCtx);
2456 }
2457
2458 return VOS_STATUS_SUCCESS;
2459 }
2460
2461 return VOS_STATUS_E_FAILURE;
2462}
2463
2464VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2465{
2466 hdd_adapter_list_node_t *pHddAdapterNode;
2467 VOS_STATUS status;
2468
2469 ENTER();
2470
2471 do
2472 {
2473 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2474 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2475 {
2476 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2477 vos_mem_free( pHddAdapterNode );
2478 }
2479 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2480
2481 EXIT();
2482
2483 return VOS_STATUS_SUCCESS;
2484}
2485
2486void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2487{
2488 v_U8_t addIE[1] = {0};
2489
2490 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2491 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2492 eANI_BOOLEAN_FALSE) )
2493 {
2494 hddLog(LOGE,
2495 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2496 }
2497
2498 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2499 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2500 eANI_BOOLEAN_FALSE) )
2501 {
2502 hddLog(LOGE,
2503 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2504 }
2505
2506 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2507 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2508 eANI_BOOLEAN_FALSE) )
2509 {
2510 hddLog(LOGE,
2511 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2512 }
2513}
2514
2515VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2516{
2517 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2518 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2519 union iwreq_data wrqu;
2520
2521 ENTER();
2522
2523 switch(pAdapter->device_mode)
2524 {
2525 case WLAN_HDD_INFRA_STATION:
2526 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002527 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002528 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2529 {
2530 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
2531 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2532 pAdapter->sessionId,
2533 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2534 else
2535 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2536 pAdapter->sessionId,
2537 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2538 //success implies disconnect command got queued up successfully
2539 if(halStatus == eHAL_STATUS_SUCCESS)
2540 {
2541 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
2542 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2543 }
2544 memset(&wrqu, '\0', sizeof(wrqu));
2545 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2546 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2547 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2548 }
2549 else
2550 {
2551 hdd_abort_mac_scan(pHddCtx);
2552 }
2553
2554 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2555 {
2556 INIT_COMPLETION(pAdapter->session_close_comp_var);
2557 if (eHAL_STATUS_SUCCESS ==
2558 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2559 hdd_smeCloseSessionCallback, pAdapter))
2560 {
2561 //Block on a completion variable. Can't wait forever though.
2562 wait_for_completion_interruptible_timeout(
2563 &pAdapter->session_close_comp_var,
2564 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2565 }
2566 }
2567
2568 break;
2569
2570 case WLAN_HDD_SOFTAP:
2571 case WLAN_HDD_P2P_GO:
2572 //Any softap specific cleanup here...
2573 mutex_lock(&pHddCtx->sap_lock);
2574 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2575 {
2576 VOS_STATUS status;
2577 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2578
2579 //Stop Bss.
2580 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2581 if (VOS_IS_STATUS_SUCCESS(status))
2582 {
2583 hdd_hostapd_state_t *pHostapdState =
2584 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2585
2586 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2587
2588 if (!VOS_IS_STATUS_SUCCESS(status))
2589 {
2590 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002591 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002592 }
2593 }
2594 else
2595 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002596 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002597 }
2598 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2599
2600 if (eHAL_STATUS_FAILURE ==
2601 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2602 0, NULL, eANI_BOOLEAN_FALSE))
2603 {
2604 hddLog(LOGE,
2605 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002606 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002607 }
2608
2609 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2610 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2611 eANI_BOOLEAN_FALSE) )
2612 {
2613 hddLog(LOGE,
2614 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2615 }
2616
2617 // Reset WNI_CFG_PROBE_RSP Flags
2618 wlan_hdd_reset_prob_rspies(pAdapter);
2619 kfree(pAdapter->sessionCtx.ap.beacon);
2620 pAdapter->sessionCtx.ap.beacon = NULL;
2621 }
2622 mutex_unlock(&pHddCtx->sap_lock);
2623 break;
2624 case WLAN_HDD_MONITOR:
2625 break;
2626 default:
2627 break;
2628 }
2629
2630 EXIT();
2631 return VOS_STATUS_SUCCESS;
2632}
2633
2634VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2635{
2636 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2637 VOS_STATUS status;
2638 hdd_adapter_t *pAdapter;
2639
2640 ENTER();
2641
2642 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2643
2644 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2645 {
2646 pAdapter = pAdapterNode->pAdapter;
2647 netif_tx_disable(pAdapter->dev);
2648 netif_carrier_off(pAdapter->dev);
2649
2650 hdd_stop_adapter( pHddCtx, pAdapter );
2651
2652 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2653 pAdapterNode = pNext;
2654 }
2655
2656 EXIT();
2657
2658 return VOS_STATUS_SUCCESS;
2659}
2660
2661VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2662{
2663 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2664 VOS_STATUS status;
2665 hdd_adapter_t *pAdapter;
2666
2667 ENTER();
2668
2669 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2670
2671 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2672 {
2673 pAdapter = pAdapterNode->pAdapter;
2674 netif_tx_disable(pAdapter->dev);
2675 netif_carrier_off(pAdapter->dev);
2676
2677 //Record whether STA is associated
2678 pAdapter->sessionCtx.station.bSendDisconnect =
2679 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2680 VOS_TRUE : VOS_FALSE;
2681
2682 hdd_deinit_tx_rx(pAdapter);
2683 hdd_wmm_adapter_close(pAdapter);
2684
2685 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2686 pAdapterNode = pNext;
2687 }
2688
2689 EXIT();
2690
2691 return VOS_STATUS_SUCCESS;
2692}
2693
2694VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2695{
2696 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2697 VOS_STATUS status;
2698 hdd_adapter_t *pAdapter;
2699 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2700
2701 ENTER();
2702
2703 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2704
2705 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2706 {
2707 pAdapter = pAdapterNode->pAdapter;
2708
2709 switch(pAdapter->device_mode)
2710 {
2711 case WLAN_HDD_INFRA_STATION:
2712 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002713 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002714 hdd_init_station_mode(pAdapter);
2715 /* Open the gates for HDD to receive Wext commands */
2716 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002717 pHddCtx->scan_info.mScanPending = FALSE;
2718 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002719
2720 //Trigger the initial scan
2721 hdd_wlan_initial_scan(pAdapter);
2722
2723 //Indicate disconnect event to supplicant if associated previously
2724 if(pAdapter->sessionCtx.station.bSendDisconnect)
2725 {
2726 union iwreq_data wrqu;
2727 memset(&wrqu, '\0', sizeof(wrqu));
2728 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2729 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2730 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2731 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2732
2733#ifdef CONFIG_CFG80211
2734 /* indicate disconnected event to nl80211 */
2735 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2736 NULL, 0, GFP_KERNEL);
2737#endif
2738 }
2739 break;
2740
2741 case WLAN_HDD_SOFTAP:
2742 /* softAP can handle SSR */
2743 break;
2744
2745 case WLAN_HDD_P2P_GO:
2746#ifdef CONFIG_CFG80211
2747 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2748 __func__);
2749 /* event supplicant to restart */
2750 cfg80211_del_sta(pAdapter->dev,
2751 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
2752#endif
2753 break;
2754
2755 case WLAN_HDD_MONITOR:
2756 /* monitor interface start */
2757 break;
2758 default:
2759 break;
2760 }
2761
2762 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2763 pAdapterNode = pNext;
2764 }
2765
2766 EXIT();
2767
2768 return VOS_STATUS_SUCCESS;
2769}
2770
2771VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2772{
2773 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2774 hdd_adapter_t *pAdapter;
2775 VOS_STATUS status;
2776 v_U32_t roamId;
2777
2778 ENTER();
2779
2780 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2781
2782 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2783 {
2784 pAdapter = pAdapterNode->pAdapter;
2785
2786 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2787 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2788 {
2789 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2790 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2791
2792 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2793 init_completion(&pAdapter->disconnect_comp_var);
2794 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2795 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2796
2797 wait_for_completion_interruptible_timeout(
2798 &pAdapter->disconnect_comp_var,
2799 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2800
2801 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2802 pHddCtx->isAmpAllowed = VOS_FALSE;
2803 sme_RoamConnect(pHddCtx->hHal,
2804 pAdapter->sessionId, &(pWextState->roamProfile),
2805 &roamId);
2806 }
2807
2808 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2809 pAdapterNode = pNext;
2810 }
2811
2812 EXIT();
2813
2814 return VOS_STATUS_SUCCESS;
2815}
2816
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002817bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002818{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002819 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002820}
2821
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002822/* Once SSR is disabled then it cannot be set. */
2823void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002824{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002825 if (HDD_SSR_DISABLED == isSsrRequired)
2826 return;
2827
Jeff Johnson295189b2012-06-20 16:38:30 -07002828 isSsrRequired = value;
2829}
2830
2831VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2832 hdd_adapter_list_node_t** ppAdapterNode)
2833{
2834 VOS_STATUS status;
2835 spin_lock(&pHddCtx->hddAdapters.lock);
2836 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2837 (hdd_list_node_t**) ppAdapterNode );
2838 spin_unlock(&pHddCtx->hddAdapters.lock);
2839 return status;
2840}
2841
2842VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2843 hdd_adapter_list_node_t* pAdapterNode,
2844 hdd_adapter_list_node_t** pNextAdapterNode)
2845{
2846 VOS_STATUS status;
2847 spin_lock(&pHddCtx->hddAdapters.lock);
2848 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2849 (hdd_list_node_t*) pAdapterNode,
2850 (hdd_list_node_t**)pNextAdapterNode );
2851
2852 spin_unlock(&pHddCtx->hddAdapters.lock);
2853 return status;
2854}
2855
2856VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2857 hdd_adapter_list_node_t* pAdapterNode)
2858{
2859 VOS_STATUS status;
2860 spin_lock(&pHddCtx->hddAdapters.lock);
2861 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2862 &pAdapterNode->node );
2863 spin_unlock(&pHddCtx->hddAdapters.lock);
2864 return status;
2865}
2866
2867VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2868 hdd_adapter_list_node_t** ppAdapterNode)
2869{
2870 VOS_STATUS status;
2871 spin_lock(&pHddCtx->hddAdapters.lock);
2872 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2873 (hdd_list_node_t**) ppAdapterNode );
2874 spin_unlock(&pHddCtx->hddAdapters.lock);
2875 return status;
2876}
2877
2878VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2879 hdd_adapter_list_node_t* pAdapterNode)
2880{
2881 VOS_STATUS status;
2882 spin_lock(&pHddCtx->hddAdapters.lock);
2883 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2884 (hdd_list_node_t*) pAdapterNode );
2885 spin_unlock(&pHddCtx->hddAdapters.lock);
2886 return status;
2887}
2888
2889VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2890 hdd_adapter_list_node_t* pAdapterNode)
2891{
2892 VOS_STATUS status;
2893 spin_lock(&pHddCtx->hddAdapters.lock);
2894 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2895 (hdd_list_node_t*) pAdapterNode );
2896 spin_unlock(&pHddCtx->hddAdapters.lock);
2897 return status;
2898}
2899
2900hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2901 tSirMacAddr macAddr )
2902{
2903 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2904 hdd_adapter_t *pAdapter;
2905 VOS_STATUS status;
2906
2907 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2908
2909 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2910 {
2911 pAdapter = pAdapterNode->pAdapter;
2912
2913 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2914 macAddr, sizeof(tSirMacAddr) ) )
2915 {
2916 return pAdapter;
2917 }
2918 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2919 pAdapterNode = pNext;
2920 }
2921
2922 return NULL;
2923
2924}
2925
2926hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
2927{
2928 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2929 hdd_adapter_t *pAdapter;
2930 VOS_STATUS status;
2931
2932 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2933
2934 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2935 {
2936 pAdapter = pAdapterNode->pAdapter;
2937
2938 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
2939 IFNAMSIZ ) )
2940 {
2941 return pAdapter;
2942 }
2943 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2944 pAdapterNode = pNext;
2945 }
2946
2947 return NULL;
2948
2949}
2950
2951hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
2952{
2953 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2954 hdd_adapter_t *pAdapter;
2955 VOS_STATUS status;
2956
2957 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2958
2959 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2960 {
2961 pAdapter = pAdapterNode->pAdapter;
2962
2963 if( pAdapter && (mode == pAdapter->device_mode) )
2964 {
2965 return pAdapter;
2966 }
2967 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2968 pAdapterNode = pNext;
2969 }
2970
2971 return NULL;
2972
2973}
2974
2975//Remove this function later
2976hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
2977{
2978 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2979 hdd_adapter_t *pAdapter;
2980 VOS_STATUS status;
2981
2982 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2983
2984 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2985 {
2986 pAdapter = pAdapterNode->pAdapter;
2987
2988 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
2989 {
2990 return pAdapter;
2991 }
2992
2993 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2994 pAdapterNode = pNext;
2995 }
2996
2997 return NULL;
2998
2999}
3000
3001#ifdef CONFIG_CFG80211
3002/**---------------------------------------------------------------------------
3003
3004 \brief hdd_set_monitor_tx_adapter() -
3005
3006 This API initializes the adapter to be used while transmitting on monitor
3007 adapter.
3008
3009 \param - pHddCtx - Pointer to the HDD context.
3010 pAdapter - Adapter that will used for TX. This can be NULL.
3011 \return - None.
3012 --------------------------------------------------------------------------*/
3013void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3014{
3015 hdd_adapter_t *pMonAdapter;
3016
3017 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3018
3019 if( NULL != pMonAdapter )
3020 {
3021 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3022 }
3023}
3024#endif
3025/**---------------------------------------------------------------------------
3026
3027 \brief hdd_select_queue() -
3028
3029 This API returns the operating channel of the requested device mode
3030
3031 \param - pHddCtx - Pointer to the HDD context.
3032 - mode - Device mode for which operating channel is required
3033 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3034 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3035 \return - channel number. "0" id the requested device is not found OR it is not connected.
3036 --------------------------------------------------------------------------*/
3037v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3038{
3039 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3040 VOS_STATUS status;
3041 hdd_adapter_t *pAdapter;
3042 v_U8_t operatingChannel = 0;
3043
3044 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3045
3046 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3047 {
3048 pAdapter = pAdapterNode->pAdapter;
3049
3050 if( mode == pAdapter->device_mode )
3051 {
3052 switch(pAdapter->device_mode)
3053 {
3054 case WLAN_HDD_INFRA_STATION:
3055 case WLAN_HDD_P2P_CLIENT:
3056 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3057 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3058 break;
3059 case WLAN_HDD_SOFTAP:
3060 case WLAN_HDD_P2P_GO:
3061 /*softap connection info */
3062 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3063 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3064 break;
3065 default:
3066 break;
3067 }
3068
3069 break; //Found the device of interest. break the loop
3070 }
3071
3072 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3073 pAdapterNode = pNext;
3074 }
3075 return operatingChannel;
3076}
3077
3078#ifdef WLAN_FEATURE_PACKET_FILTERING
3079/**---------------------------------------------------------------------------
3080
3081 \brief hdd_set_multicast_list() -
3082
3083 This used to set the multicast address list.
3084
3085 \param - dev - Pointer to the WLAN device.
3086 - skb - Pointer to OS packet (sk_buff).
3087 \return - success/fail
3088
3089 --------------------------------------------------------------------------*/
3090static void hdd_set_multicast_list(struct net_device *dev)
3091{
3092 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3093 hdd_context_t *pHddCtx;
3094 int mc_count;
3095 int i = 0;
3096 struct netdev_hw_addr *ha;
3097 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3098 if (NULL == pHddCtx)
3099 {
3100 hddLog(VOS_TRACE_LEVEL_ERROR,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003101 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003102 return;
3103 }
3104
3105 if (dev->flags & IFF_ALLMULTI)
3106 {
3107 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003108 "%s: allow all multicast frames", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003109 pHddCtx->mc_addr_list.mc_cnt = 0;
3110 }
3111 else
3112 {
3113 mc_count = netdev_mc_count(dev);
3114 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003115 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003116 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3117 {
3118 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003119 "%s: No free filter available; allow all multicast frames", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003120 pHddCtx->mc_addr_list.mc_cnt = 0;
3121 return;
3122 }
3123
3124 pHddCtx->mc_addr_list.mc_cnt = mc_count;
3125
3126 netdev_for_each_mc_addr(ha, dev) {
3127 if (i == mc_count)
3128 break;
3129 memset(&(pHddCtx->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3130 memcpy(&(pHddCtx->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3131 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = %02x:%02x:%02x:%02x:%02x:%02x",
3132 __func__, i,
3133 pHddCtx->mc_addr_list.addr[i][0], pHddCtx->mc_addr_list.addr[i][1],
3134 pHddCtx->mc_addr_list.addr[i][2], pHddCtx->mc_addr_list.addr[i][3],
3135 pHddCtx->mc_addr_list.addr[i][4], pHddCtx->mc_addr_list.addr[i][5]);
3136 i++;
3137 }
3138 }
3139 return;
3140}
3141#endif
3142
3143/**---------------------------------------------------------------------------
3144
3145 \brief hdd_select_queue() -
3146
3147 This function is registered with the Linux OS for network
3148 core to decide which queue to use first.
3149
3150 \param - dev - Pointer to the WLAN device.
3151 - skb - Pointer to OS packet (sk_buff).
3152 \return - ac, Queue Index/access category corresponding to UP in IP header
3153
3154 --------------------------------------------------------------------------*/
3155v_U16_t hdd_select_queue(struct net_device *dev,
3156 struct sk_buff *skb)
3157{
3158 return hdd_wmm_select_queue(dev, skb);
3159}
3160
3161
3162/**---------------------------------------------------------------------------
3163
3164 \brief hdd_wlan_initial_scan() -
3165
3166 This function triggers the initial scan
3167
3168 \param - pAdapter - Pointer to the HDD adapter.
3169
3170 --------------------------------------------------------------------------*/
3171void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3172{
3173 tCsrScanRequest scanReq;
3174 tCsrChannelInfo channelInfo;
3175 eHalStatus halStatus;
3176 unsigned long scanId;
3177 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3178
3179 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3180 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3181 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3182
3183 if(sme_Is11dSupported(pHddCtx->hHal))
3184 {
3185 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3186 if ( HAL_STATUS_SUCCESS( halStatus ) )
3187 {
3188 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3189 if( !scanReq.ChannelInfo.ChannelList )
3190 {
3191 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3192 vos_mem_free(channelInfo.ChannelList);
3193 return;
3194 }
3195 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3196 channelInfo.numOfChannels);
3197 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3198 vos_mem_free(channelInfo.ChannelList);
3199 }
3200
3201 scanReq.scanType = eSIR_PASSIVE_SCAN;
3202 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3203 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3204 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3205 }
3206 else
3207 {
3208 scanReq.scanType = eSIR_ACTIVE_SCAN;
3209 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3210 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3211 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3212 }
3213
3214 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3215 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3216 {
3217 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3218 __func__, halStatus );
3219 }
3220
3221 if(sme_Is11dSupported(pHddCtx->hHal))
3222 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3223}
3224
3225struct fullPowerContext
3226{
3227 struct completion completion;
3228 unsigned int magic;
3229};
3230#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3231
3232/**---------------------------------------------------------------------------
3233
3234 \brief hdd_full_power_callback() - HDD full power callback function
3235
3236 This is the function invoked by SME to inform the result of a full power
3237 request issued by HDD
3238
3239 \param - callbackcontext - Pointer to cookie
3240 \param - status - result of request
3241
3242 \return - None
3243
3244 --------------------------------------------------------------------------*/
3245static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3246{
3247 struct fullPowerContext *pContext = callbackContext;
3248
3249 hddLog(VOS_TRACE_LEVEL_INFO,
3250 "%s: context = %p, status = %d", pContext, status);
3251
3252 if (NULL == callbackContext)
3253 {
3254 hddLog(VOS_TRACE_LEVEL_ERROR,
3255 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003256 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003257 return;
3258 }
3259
3260 /* there is a race condition that exists between this callback function
3261 and the caller since the caller could time out either before or
3262 while this code is executing. we'll assume the timeout hasn't
3263 occurred, but we'll verify that right before we save our work */
3264
3265 if (POWER_CONTEXT_MAGIC != pContext->magic)
3266 {
3267 /* the caller presumably timed out so there is nothing we can do */
3268 hddLog(VOS_TRACE_LEVEL_WARN,
3269 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003270 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003271 return;
3272 }
3273
3274 /* the race is on. caller could have timed out immediately after
3275 we verified the magic, but if so, caller will wait a short time
3276 for us to notify the caller, so the context will stay valid */
3277 complete(&pContext->completion);
3278}
3279
3280/**---------------------------------------------------------------------------
3281
3282 \brief hdd_wlan_exit() - HDD WLAN exit function
3283
3284 This is the driver exit point (invoked during rmmod)
3285
3286 \param - pHddCtx - Pointer to the HDD Context
3287
3288 \return - None
3289
3290 --------------------------------------------------------------------------*/
3291void hdd_wlan_exit(hdd_context_t *pHddCtx)
3292{
3293 eHalStatus halStatus;
3294 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3295 VOS_STATUS vosStatus;
3296#ifdef ANI_BUS_TYPE_SDIO
3297 struct sdio_func *sdio_func_dev = NULL;
3298#endif // ANI_BUS_TYPE_SDIO
3299#ifdef CONFIG_CFG80211
3300 struct wiphy *wiphy = pHddCtx->wiphy;
3301#endif
3302#ifdef FEATURE_WLAN_INTEGRATED_SOC
3303 hdd_adapter_t* pAdapter;
3304#endif
3305 struct fullPowerContext powerContext;
3306 long lrc;
3307
3308 ENTER();
3309
Ng Chilam1322ea32012-12-27 17:33:08 -08003310#ifdef ANI_MANF_DIAG
3311 if (VOS_FTM_MODE != hdd_get_conparam())
3312#endif /* ANI_MANF_DIAG */
3313 {
3314 // Unloading, restart logic is no more required.
3315 wlan_hdd_restart_deinit(pHddCtx);
3316 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003317
Jeff Johnson295189b2012-06-20 16:38:30 -07003318#ifdef CONFIG_CFG80211
3319#ifdef WLAN_SOFTAP_FEATURE
3320 if (VOS_STA_SAP_MODE != hdd_get_conparam())
3321#endif
3322 {
3323#ifdef ANI_MANF_DIAG
3324 if (VOS_FTM_MODE != hdd_get_conparam())
3325#endif /* ANI_MANF_DIAG */
3326 {
3327 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3328 WLAN_HDD_INFRA_STATION);
3329 if (pAdapter == NULL)
3330 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3331
3332 if (pAdapter != NULL)
3333 {
3334 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3335 hdd_UnregisterWext(pAdapter->dev);
3336 }
3337 }
3338 }
3339#endif
3340
3341#ifdef ANI_MANF_DIAG
3342 if (VOS_FTM_MODE == hdd_get_conparam())
3343 {
3344 wlan_hdd_ftm_close(pHddCtx);
3345 goto free_hdd_ctx;
3346 }
3347#endif
3348 //Stop the Interface TX queue.
3349 //netif_tx_disable(pWlanDev);
3350 //netif_carrier_off(pWlanDev);
3351
Jeff Johnson295189b2012-06-20 16:38:30 -07003352#ifdef FEATURE_WLAN_INTEGRATED_SOC
3353#ifdef WLAN_SOFTAP_FEATURE
3354 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3355 {
3356 pAdapter = hdd_get_adapter(pHddCtx,
3357 WLAN_HDD_SOFTAP);
3358 }
3359 else
3360 {
3361#endif
3362#ifdef ANI_MANF_DIAG
3363 if (VOS_FTM_MODE != hdd_get_conparam())
3364#endif /* ANI_MANF_DIAG */
3365 {
3366 pAdapter = hdd_get_adapter(pHddCtx,
3367 WLAN_HDD_INFRA_STATION);
3368 }
3369#ifdef WLAN_SOFTAP_FEATURE
3370 }
3371#endif
3372 /* DeRegister with platform driver as client for Suspend/Resume */
3373 vosStatus = hddDeregisterPmOps(pHddCtx);
3374 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3375 {
3376 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3377 VOS_ASSERT(0);
3378 }
3379
3380 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3381 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3382 {
3383 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3384 }
3385#endif //FEATURE_WLAN_INTEGRATED_SOC
3386
Chilam NG571c65a2013-01-19 12:27:36 +05303387#ifdef FEATURE_WLAN_TDLS
3388 wlan_hdd_tdls_exit();
3389#endif
3390
Jeff Johnson295189b2012-06-20 16:38:30 -07003391 // Cancel any outstanding scan requests. We are about to close all
3392 // of our adapters, but an adapter structure is what SME passes back
3393 // to our callback function. Hence if there are any outstanding scan
3394 // requests then there is a race condition between when the adapter
3395 // is closed and when the callback is invoked. We try to resolve that
3396 // race condition here by canceling any outstanding scans before we
3397 // close the adapters.
3398 // Note that the scans may be cancelled in an asynchronous manner, so
3399 // ideally there needs to be some kind of synchronization. Rather than
3400 // introduce a new synchronization here, we will utilize the fact that
3401 // we are about to Request Full Power, and since that is synchronized,
3402 // the expectation is that by the time Request Full Power has completed,
3403 // all scans will be cancelled.
3404 hdd_abort_mac_scan( pHddCtx );
3405
3406 //Disable IMPS/BMPS as we do not want the device to enter any power
3407 //save mode during shutdown
3408 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3409 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3410 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3411
3412 //Ensure that device is in full power as we will touch H/W during vos_Stop
3413 init_completion(&powerContext.completion);
3414 powerContext.magic = POWER_CONTEXT_MAGIC;
3415
3416 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3417 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3418
3419 if (eHAL_STATUS_SUCCESS != halStatus)
3420 {
3421 if (eHAL_STATUS_PMC_PENDING == halStatus)
3422 {
3423 /* request was sent -- wait for the response */
3424 lrc = wait_for_completion_interruptible_timeout(
3425 &powerContext.completion,
3426 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3427 /* either we have a response or we timed out
3428 either way, first invalidate our magic */
3429 powerContext.magic = 0;
3430 if (lrc <= 0)
3431 {
3432 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003433 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003434 /* there is a race condition such that the callback
3435 function could be executing at the same time we are. of
3436 primary concern is if the callback function had already
3437 verified the "magic" but hasn't yet set the completion
3438 variable. Since the completion variable is on our
3439 stack, we'll delay just a bit to make sure the data is
3440 still valid if that is the case */
3441 msleep(50);
3442 }
3443 }
3444 else
3445 {
3446 hddLog(VOS_TRACE_LEVEL_ERROR,
3447 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003448 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003449 VOS_ASSERT(0);
3450 /* continue -- need to clean up as much as possible */
3451 }
3452 }
3453
3454 // Unregister the Net Device Notifier
3455 unregister_netdevice_notifier(&hdd_netdev_notifier);
3456
Jeff Johnson295189b2012-06-20 16:38:30 -07003457 hdd_stop_all_adapters( pHddCtx );
3458
3459#ifdef ANI_BUS_TYPE_SDIO
3460 sdio_func_dev = libra_getsdio_funcdev();
3461
3462 if(sdio_func_dev == NULL)
3463 {
3464 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
3465 VOS_ASSERT(0);
3466 return;
3467 }
3468
3469 sd_claim_host(sdio_func_dev);
3470
3471 /* Disable SDIO IRQ since we are exiting */
3472 libra_enable_sdio_irq(sdio_func_dev, 0);
3473
3474 sd_release_host(sdio_func_dev);
3475#endif // ANI_BUS_TYPE_SDIO
3476
3477#ifdef WLAN_BTAMP_FEATURE
3478 vosStatus = WLANBAP_Stop(pVosContext);
3479 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3480 {
3481 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3482 "%s: Failed to stop BAP",__func__);
3483 }
3484#endif //WLAN_BTAMP_FEATURE
3485
3486 //Stop all the modules
3487 vosStatus = vos_stop( pVosContext );
3488 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3489 {
3490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3491 "%s: Failed to stop VOSS",__func__);
3492 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3493 }
3494
3495#ifdef ANI_BUS_TYPE_SDIO
3496 vosStatus = WLANBAL_Stop( pVosContext );
3497
3498 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN BAL STOP\n");
3499 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3500 {
3501 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3502 "%s: Failed to stop BAL",__func__);
3503 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3504 }
3505
3506 msleep(50);
3507 //Put the chip is standby before asserting deep sleep
3508 vosStatus = WLANBAL_SuspendChip( pVosContext );
3509
3510 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN Suspend Chip\n");
3511
3512 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3513 {
3514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3515 "%s: Failed to suspend chip ",__func__);
3516 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3517 }
3518 //Invoke SAL stop
3519 vosStatus = WLANSAL_Stop( pVosContext );
3520 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3521 {
3522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3523 "%s: Failed to stop SAL",__func__);
3524 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3525 }
3526
3527#endif // ANI_BUS_TYPE_SDIO
3528
3529 //Assert Deep sleep signal now to put Libra HW in lowest power state
3530 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
3531 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3532
3533 //Vote off any PMIC voltage supplies
3534 vos_chipPowerDown(NULL, NULL, NULL);
3535
3536 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3537
3538 //Clean up HDD Nlink Service
3539 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
3540 nl_srv_exit();
3541
3542 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07003543 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003544
3545 //Close the scheduler before calling vos_close to make sure no thread is
3546 // scheduled after the each module close is called i.e after all the data
3547 // structures are freed.
3548 vosStatus = vos_sched_close( pVosContext );
3549 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3550 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3551 "%s: Failed to close VOSS Scheduler",__func__);
3552 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3553 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003554#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003555#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3556 /* Destroy the wake lock */
3557 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3558#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003559 /* Destroy the wake lock */
3560 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003561#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003562
3563 //Close VOSS
3564 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3565 vos_close(pVosContext);
3566
3567#ifdef ANI_BUS_TYPE_SDIO
3568 vosStatus = WLANBAL_Close(pVosContext);
3569 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3570 {
3571 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3572 "%s: Failed to close BAL",__func__);
3573 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3574 }
3575 hddLog(VOS_TRACE_LEVEL_ERROR,"Returned WLAN BAL CLOSE\n\n\n\n");
3576#endif // ANI_BUS_TYPE_SDIO
3577
3578 //Close Watchdog
3579 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3580 vos_watchdog_close(pVosContext);
3581
3582 /* Cancel the vote for XO Core ON.
3583 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3584 * exited at this point
3585 */
3586 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3587 " when WLAN is turned OFF\n");
3588 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3589 {
3590 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3591 " Not returning failure."
3592 " Power consumed will be high\n");
3593 }
3594
3595 hdd_close_all_adapters( pHddCtx );
3596
3597
3598 //Free up dynamically allocated members inside HDD Adapter
3599 kfree(pHddCtx->cfg_ini);
3600 pHddCtx->cfg_ini= NULL;
3601
3602 /* free the power on lock from platform driver */
3603 if (free_riva_power_on_lock("wlan"))
3604 {
3605 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3606 __func__);
3607 }
3608
3609#ifdef ANI_MANF_DIAG
3610free_hdd_ctx:
3611#endif
3612#ifdef CONFIG_CFG80211
3613 wiphy_unregister(wiphy) ;
3614 wiphy_free(wiphy) ;
3615#else
3616 vos_mem_free( pHddCtx );
3617#endif
3618 if (hdd_is_ssr_required())
3619 {
3620 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003621 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003622 msleep(5000);
3623 }
3624 hdd_set_ssr_required (VOS_FALSE);
3625}
3626
3627
3628/**---------------------------------------------------------------------------
3629
3630 \brief hdd_update_config_from_nv() - Function to update the contents of
3631 the running configuration with parameters taken from NV storage
3632
3633 \param - pHddCtx - Pointer to the HDD global context
3634
3635 \return - VOS_STATUS_SUCCESS if successful
3636
3637 --------------------------------------------------------------------------*/
3638static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3639{
3640#ifndef FEATURE_WLAN_INTEGRATED_SOC
3641 eHalStatus halStatus;
3642#endif
3643
3644#ifdef FEATURE_WLAN_INTEGRATED_SOC
3645 v_BOOL_t itemIsValid = VOS_FALSE;
3646 VOS_STATUS status;
3647 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3648 v_U8_t macLoop;
3649
3650 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3651 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3652 if(status != VOS_STATUS_SUCCESS)
3653 {
3654 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3655 return VOS_STATUS_E_FAILURE;
3656 }
3657
3658 if (itemIsValid == VOS_TRUE)
3659 {
3660 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3661 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3662 VOS_MAX_CONCURRENCY_PERSONA);
3663 if(status != VOS_STATUS_SUCCESS)
3664 {
3665 /* Get MAC from NV fail, not update CFG info
3666 * INI MAC value will be used for MAC setting */
3667 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3668 return VOS_STATUS_E_FAILURE;
3669 }
3670
3671 /* If first MAC is not valid, treat all others are not valid
3672 * Then all MACs will be got from ini file */
3673 if(vos_is_macaddr_zero(&macFromNV[0]))
3674 {
3675 /* MAC address in NV file is not configured yet */
3676 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3677 return VOS_STATUS_E_INVAL;
3678 }
3679
3680 /* Get MAC address from NV, update CFG info */
3681 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3682 {
3683 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3684 {
3685 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3686 /* This MAC is not valid, skip it
3687 * This MAC will be got from ini file */
3688 }
3689 else
3690 {
3691 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3692 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3693 VOS_MAC_ADDR_SIZE);
3694 }
3695 }
3696 }
3697 else
3698 {
3699 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3700 return VOS_STATUS_E_FAILURE;
3701 }
3702#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3703
3704#ifndef FEATURE_WLAN_INTEGRATED_SOC
3705#if 1 /* need to fix for concurrency */
3706 // Set the MAC Address
3707 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3708 halStatus = ccmCfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3709 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3710 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]),
3711 hdd_set_mac_addr_cb, VOS_FALSE );
3712
3713 if (!HAL_STATUS_SUCCESS( halStatus ))
3714 {
3715 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3716 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
3717 return VOS_STATUS_E_FAILURE;
3718 }
3719#endif
3720#endif
3721
3722 return VOS_STATUS_SUCCESS;
3723}
3724
3725/**---------------------------------------------------------------------------
3726
3727 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3728
3729 \param - pAdapter - Pointer to the HDD
3730
3731 \return - None
3732
3733 --------------------------------------------------------------------------*/
3734VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3735{
3736 eHalStatus halStatus;
3737 v_U32_t listenInterval;
3738
3739#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
3740 /* In the non-integrated architecture we update the configuration from
3741 the INI file and from NV after vOSS has been started
3742 */
3743
3744 // Apply the cfg.ini to cfg.dat
3745 if (FALSE == hdd_update_config_dat(pHddCtx))
3746 {
3747 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3748 return VOS_STATUS_E_FAILURE;
3749 }
3750
3751 // Apply the NV to cfg.dat
3752 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3753 {
3754 hddLog(VOS_TRACE_LEVEL_FATAL,
3755 "%s: config update from NV failed", __func__ );
3756 return VOS_STATUS_E_FAILURE;
3757 }
3758#endif // FEATURE_WLAN_NON_INTEGRATED_SOC
3759
3760 // Send ready indication to the HDD. This will kick off the MAC
3761 // into a 'running' state and should kick off an initial scan.
3762 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3763 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3764 {
3765 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3766 "code %08d [x%08x]",__func__, halStatus, halStatus );
3767 return VOS_STATUS_E_FAILURE;
3768 }
3769
3770 // Set default LI into HDD context,
3771 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3772 // And RIVA will crash
3773 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3774 pHddCtx->hdd_actual_LI_value = listenInterval;
3775
3776 return VOS_STATUS_SUCCESS;
3777}
3778
3779#ifdef ANI_BUS_TYPE_SDIO
3780
3781#ifndef ANI_MANF_DIAG
3782// Routine to initialize the PMU
3783void wlan_hdd_enable_deepsleep(v_VOID_t * pVosContext)
3784{
3785/*-------------- Need to fix this correctly while doing Deepsleep testing
3786 tANI_U32 regValue = 0;
3787
3788 regValue = QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_DEEP_SLEEP_EN_MASK |
3789 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_AON_MASK_MASK |
3790 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_SW_MASK_MASK |
3791 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_2P3_LPM_MASK_MASK;
3792
3793 WLANBAL_WriteRegister(pVosContext, QWLAN_PMU_LDO_CTRL_REG_REG, regValue);
3794---------------------*/
3795
3796 return;
3797}
3798#endif
3799#endif
3800
3801/* wake lock APIs for HDD */
3802void hdd_prevent_suspend(void)
3803{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003804#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003805 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003806#else
3807 wcnss_prevent_suspend();
3808#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003809}
3810
3811void hdd_allow_suspend(void)
3812{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003813#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003814 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003815#else
3816 wcnss_allow_suspend();
3817#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003818}
3819
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003820void hdd_allow_suspend_timeout(v_U32_t timeout)
3821{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003822#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003823 wake_lock_timeout(&wlan_wake_lock, timeout);
3824#else
3825 /* Do nothing as there is no API in wcnss for timeout*/
3826#endif
3827}
3828
Jeff Johnson295189b2012-06-20 16:38:30 -07003829/**---------------------------------------------------------------------------
3830
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003831 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3832 information between Host and Riva
3833
3834 This function gets reported version of FW
3835 It also finds the version of Riva headers used to compile the host
3836 It compares the above two and prints a warning if they are different
3837 It gets the SW and HW version string
3838 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3839 indicating the features they support through a bitmap
3840
3841 \param - pHddCtx - Pointer to HDD context
3842
3843 \return - void
3844
3845 --------------------------------------------------------------------------*/
3846
3847void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3848{
3849
3850 tSirVersionType versionCompiled;
3851 tSirVersionType versionReported;
3852 tSirVersionString versionString;
3853 tANI_U8 fwFeatCapsMsgSupported = 0;
3854 VOS_STATUS vstatus;
3855
3856 /* retrieve and display WCNSS version information */
3857 do {
3858
3859 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3860 &versionCompiled);
3861 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3862 {
3863 hddLog(VOS_TRACE_LEVEL_FATAL,
3864 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003865 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003866 break;
3867 }
3868
3869 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3870 &versionReported);
3871 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3872 {
3873 hddLog(VOS_TRACE_LEVEL_FATAL,
3874 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003875 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003876 break;
3877 }
3878
3879 if ((versionCompiled.major != versionReported.major) ||
3880 (versionCompiled.minor != versionReported.minor) ||
3881 (versionCompiled.version != versionReported.version) ||
3882 (versionCompiled.revision != versionReported.revision))
3883 {
3884 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3885 "Host expected %u.%u.%u.%u\n",
3886 WLAN_MODULE_NAME,
3887 (int)versionReported.major,
3888 (int)versionReported.minor,
3889 (int)versionReported.version,
3890 (int)versionReported.revision,
3891 (int)versionCompiled.major,
3892 (int)versionCompiled.minor,
3893 (int)versionCompiled.version,
3894 (int)versionCompiled.revision);
3895 }
3896 else
3897 {
3898 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3899 WLAN_MODULE_NAME,
3900 (int)versionReported.major,
3901 (int)versionReported.minor,
3902 (int)versionReported.version,
3903 (int)versionReported.revision);
3904 }
3905
3906 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3907 versionString,
3908 sizeof(versionString));
3909 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3910 {
3911 hddLog(VOS_TRACE_LEVEL_FATAL,
3912 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003913 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003914 break;
3915 }
3916
3917 pr_info("%s: WCNSS software version %s\n",
3918 WLAN_MODULE_NAME, versionString);
3919
3920 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3921 versionString,
3922 sizeof(versionString));
3923 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3924 {
3925 hddLog(VOS_TRACE_LEVEL_FATAL,
3926 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003927 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003928 break;
3929 }
3930
3931 pr_info("%s: WCNSS hardware version %s\n",
3932 WLAN_MODULE_NAME, versionString);
3933
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003934 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3935 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003936 send the message only if it the riva is 1.1
3937 minor numbers for different riva branches:
3938 0 -> (1.0)Mainline Build
3939 1 -> (1.1)Mainline Build
3940 2->(1.04) Stability Build
3941 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003942 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003943 ((versionReported.minor>=1) && (versionReported.version>=1)))
3944 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3945 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003946
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003947 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003948 {
3949#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3950 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3951 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3952#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003953 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08003954 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003955
3956 } while (0);
3957
3958}
3959
3960/**---------------------------------------------------------------------------
3961
Jeff Johnson295189b2012-06-20 16:38:30 -07003962 \brief hdd_wlan_startup() - HDD init function
3963
3964 This is the driver startup code executed once a WLAN device has been detected
3965
3966 \param - dev - Pointer to the underlying device
3967
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003968 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07003969
3970 --------------------------------------------------------------------------*/
3971
3972int hdd_wlan_startup(struct device *dev )
3973{
3974 VOS_STATUS status;
3975 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07003976 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003977 hdd_context_t *pHddCtx = NULL;
3978 v_CONTEXT_t pVosContext= NULL;
3979#ifdef WLAN_BTAMP_FEATURE
3980 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
3981 WLANBAP_ConfigType btAmpConfig;
3982 hdd_config_t *pConfig;
3983#endif
3984 int ret;
3985#ifdef CONFIG_CFG80211
3986 struct wiphy *wiphy;
3987#endif
3988#ifdef ANI_BUS_TYPE_SDIO
3989 struct sdio_func *sdio_func_dev = dev_to_sdio_func(dev);
3990#endif //ANI_BUS_TYPE_SDIO
3991
3992 ENTER();
3993#ifdef CONFIG_CFG80211
3994 /*
3995 * cfg80211: wiphy allocation
3996 */
3997 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
3998
3999 if(wiphy == NULL)
4000 {
4001 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004002 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004003 }
4004
4005 pHddCtx = wiphy_priv(wiphy);
4006
4007#else
4008
4009 pHddCtx = vos_mem_malloc ( sizeof( hdd_context_t ) );
4010 if(pHddCtx == NULL)
4011 {
4012 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004013 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07004014 }
4015
4016#endif
4017 //Initialize the adapter context to zeros.
4018 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4019
4020#ifdef CONFIG_CFG80211
4021 pHddCtx->wiphy = wiphy;
4022#endif
4023 hdd_prevent_suspend();
4024 pHddCtx->isLoadUnloadInProgress = TRUE;
4025
4026 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4027
4028 /*Get vos context here bcoz vos_open requires it*/
4029 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4030
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004031 if(pVosContext == NULL)
4032 {
4033 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4034 goto err_free_hdd_context;
4035 }
4036
Jeff Johnson295189b2012-06-20 16:38:30 -07004037 //Save the Global VOSS context in adapter context for future.
4038 pHddCtx->pvosContext = pVosContext;
4039
4040 //Save the adapter context in global context for future.
4041 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4042
4043#ifdef ANI_BUS_TYPE_SDIO
4044 // Set the private data for the device to our adapter.
4045 libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
4046 atomic_set(&pHddCtx->sdio_claim_count, 0);
4047#endif // ANI_BUS_TYPE_SDIO
4048
4049 pHddCtx->parent_dev = dev;
4050
4051 init_completion(&pHddCtx->full_pwr_comp_var);
4052 init_completion(&pHddCtx->standby_comp_var);
4053 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004054 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004055 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004056
4057 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4058
4059 // Load all config first as TL config is needed during vos_open
4060 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4061 if(pHddCtx->cfg_ini == NULL)
4062 {
4063 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4064 goto err_free_hdd_context;
4065 }
4066
4067 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4068
4069 // Read and parse the qcom_cfg.ini file
4070 status = hdd_parse_config_ini( pHddCtx );
4071 if ( VOS_STATUS_SUCCESS != status )
4072 {
4073 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4074 __func__, WLAN_INI_FILE);
4075 goto err_config;
4076 }
4077
4078#ifdef CONFIG_CFG80211
4079 /*
4080 * cfg80211: Initialization and registration ...
4081 */
4082 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4083 {
4084 hddLog(VOS_TRACE_LEVEL_FATAL,
4085 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4086 goto err_wiphy_reg;
4087 }
4088#endif
4089
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004090 // Update VOS trace levels based upon the cfg.ini
4091 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4092 pHddCtx->cfg_ini->vosTraceEnableBAP);
4093 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4094 pHddCtx->cfg_ini->vosTraceEnableTL);
4095 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4096 pHddCtx->cfg_ini->vosTraceEnableWDI);
4097 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4098 pHddCtx->cfg_ini->vosTraceEnableHDD);
4099 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4100 pHddCtx->cfg_ini->vosTraceEnableSME);
4101 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4102 pHddCtx->cfg_ini->vosTraceEnablePE);
4103 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4104 pHddCtx->cfg_ini->vosTraceEnableWDA);
4105 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4106 pHddCtx->cfg_ini->vosTraceEnableSYS);
4107 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4108 pHddCtx->cfg_ini->vosTraceEnableVOSS);
4109#ifdef WLAN_SOFTAP_FEATURE
4110 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4111 pHddCtx->cfg_ini->vosTraceEnableSAP);
4112 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4113 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
4114#endif
4115
Jeff Johnson295189b2012-06-20 16:38:30 -07004116#ifdef FEATURE_WLAN_INTEGRATED_SOC
4117 // Update WDI trace levels based upon the cfg.ini
4118 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4119 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4120 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4121 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4122 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4123 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4124 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4125 pHddCtx->cfg_ini->wdiTraceEnablePAL);
4126#endif /* FEATURE_WLAN_INTEGRATED_SOC */
4127
4128#ifdef ANI_MANF_DIAG
4129 if(VOS_FTM_MODE == hdd_get_conparam())
4130 {
4131 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4132 {
4133 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4134 goto err_free_hdd_context;
4135 }
4136 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4137 return VOS_STATUS_SUCCESS;
4138 }
4139#endif
4140
4141 //Open watchdog module
4142 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4143 {
4144 status = vos_watchdog_open(pVosContext,
4145 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4146
4147 if(!VOS_IS_STATUS_SUCCESS( status ))
4148 {
4149 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
4150#ifdef CONFIG_CFG80211
4151 goto err_wiphy_reg;
4152#else
4153 goto err_config;
4154#endif
4155 }
4156 }
4157
4158 pHddCtx->isLogpInProgress = FALSE;
4159 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4160
4161#ifdef ANI_BUS_TYPE_SDIO
4162 status = WLANBAL_Open(pHddCtx->pvosContext);
4163 if(!VOS_IS_STATUS_SUCCESS(status))
4164 {
4165 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4166 "%s: Failed to open BAL",__func__);
4167 goto err_wdclose;
4168 }
4169#endif // ANI_BUS_TYPE_SDIO
4170
4171 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4172 if(!VOS_IS_STATUS_SUCCESS(status))
4173 {
4174 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
4175#ifdef ANI_BUS_TYPE_SDIO
4176 goto err_balclose;
4177#else
4178 goto err_wdclose;
4179#endif
4180 }
4181
4182
4183#ifdef ANI_BUS_TYPE_SDIO
4184 status = WLANSAL_Start(pHddCtx->pvosContext);
4185 if (!VOS_IS_STATUS_SUCCESS(status))
4186 {
4187 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
4188 goto err_clkvote;
4189 }
4190
4191 /* Start BAL */
4192 status = WLANBAL_Start(pHddCtx->pvosContext);
4193
4194 if (!VOS_IS_STATUS_SUCCESS(status))
4195 {
4196 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4197 "%s: Failed to start BAL",__func__);
4198 goto err_salstop;
4199 }
4200#endif // ANI_BUS_TYPE_SDIO
4201
4202#ifdef MSM_PLATFORM_7x30
4203 /* FIXME: Volans 2.0 configuration. Reconfigure 1.3v SW supply to 1.3v. It will be configured to
4204 * 1.4v in vos_ChipPowerup() routine above
4205 */
4206#endif
4207
4208 status = vos_open( &pVosContext, 0);
4209 if ( !VOS_IS_STATUS_SUCCESS( status ))
4210 {
4211 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
4212 goto err_balstop;
4213 }
4214
4215 /* Save the hal context in Adapter */
4216 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4217
4218 if ( NULL == pHddCtx->hHal )
4219 {
4220 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
4221 goto err_vosclose;
4222 }
4223
Jeff Johnsone7245742012-09-05 17:12:55 -07004224#ifdef FEATURE_WLAN_INTEGRATED_SOC
4225 /* Vos preStart is calling */
4226 /* vos preStart which does cfg download should be called before set sme config which accesses/sets some cfgs */
4227 status = vos_preStart( pHddCtx->pvosContext );
4228 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4229 {
4230 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
4231 goto err_vosclose;
4232 }
4233#endif
4234
Jeff Johnson295189b2012-06-20 16:38:30 -07004235 // Set the SME configuration parameters...
4236 status = hdd_set_sme_config( pHddCtx );
4237
4238 if ( VOS_STATUS_SUCCESS != status )
4239 {
4240 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
4241 goto err_vosclose;
4242 }
4243
4244 //Initialize the WMM module
4245 status = hdd_wmm_init(pHddCtx);
4246 if (!VOS_IS_STATUS_SUCCESS(status))
4247 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004248 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004249 goto err_vosclose;
4250 }
4251
4252#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnson295189b2012-06-20 16:38:30 -07004253 /* In the integrated architecture we update the configuration from
4254 the INI file and from NV before vOSS has been started so that
4255 the final contents are available to send down to the cCPU */
4256
4257 // Apply the cfg.ini to cfg.dat
4258 if (FALSE == hdd_update_config_dat(pHddCtx))
4259 {
4260 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4261 goto err_vosclose;
4262 }
4263
4264 // Apply the NV to cfg.dat
4265 /* Prima Update MAC address only at here */
4266 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4267 {
4268#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4269 /* There was not a valid set of MAC Addresses in NV. See if the
4270 default addresses were modified by the cfg.ini settings. If so,
4271 we'll use them, but if not, we'll autogenerate a set of MAC
4272 addresses based upon the device serial number */
4273
4274 static const v_MACADDR_t default_address =
4275 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4276 unsigned int serialno;
4277 int i;
4278
4279 serialno = wcnss_get_serial_number();
4280 if ((0 != serialno) &&
4281 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4282 sizeof(default_address))))
4283 {
4284 /* cfg.ini has the default address, invoke autogen logic */
4285
4286 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4287 bytes of the serial number that can be used to generate
4288 the other 3 bytes of the MAC address. Mask off all but
4289 the lower 3 bytes (this will also make sure we don't
4290 overflow in the next step) */
4291 serialno &= 0x00FFFFFF;
4292
4293 /* we need a unique address for each session */
4294 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4295
4296 /* autogen all addresses */
4297 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4298 {
4299 /* start with the entire default address */
4300 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4301 /* then replace the lower 3 bytes */
4302 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4303 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4304 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4305
4306 serialno++;
4307 }
4308
4309 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4310 MAC_ADDRESS_STR,
4311 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4312 }
4313 else
4314#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4315 {
4316 hddLog(VOS_TRACE_LEVEL_ERROR,
4317 "%s: Invalid MAC address in NV, using MAC from ini file "
4318 MAC_ADDRESS_STR, __func__,
4319 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4320 }
4321 }
4322 {
4323 eHalStatus halStatus;
4324 // Set the MAC Address
4325 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4326 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4327 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4328 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4329
4330 if (!HAL_STATUS_SUCCESS( halStatus ))
4331 {
4332 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4333 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004334 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004335 }
4336 }
4337#endif // FEATURE_WLAN_INTEGRATED_SOC
4338
4339 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4340 Note: Firmware image will be read and downloaded inside vos_start API */
4341 status = vos_start( pHddCtx->pvosContext );
4342 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4343 {
4344 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4345 goto err_vosclose;
4346 }
4347
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004348 /* Exchange capability info between Host and FW and also get versioning info from FW */
4349 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004350
4351 status = hdd_post_voss_start_config( pHddCtx );
4352 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4353 {
4354 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4355 __func__);
4356 goto err_vosstop;
4357 }
4358
4359#ifdef WLAN_SOFTAP_FEATURE
4360 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4361 {
4362 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4363 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4364 }
4365 else
4366 {
4367#endif
4368 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4369 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4370 if (pAdapter != NULL)
4371 {
4372#ifdef WLAN_FEATURE_P2P
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304373 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004374 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304375 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4376 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4377 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004378
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304379 /* Generate the P2P Device Address. This consists of the device's
4380 * primary MAC address with the locally administered bit set.
4381 */
4382 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004383 }
4384 else
4385 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304386 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4387 if (p2p_dev_addr != NULL)
4388 {
4389 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4390 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4391 }
4392 else
4393 {
4394 hddLog(VOS_TRACE_LEVEL_FATAL,
4395 "%s: Failed to allocate mac_address for p2p_device",
4396 __func__);
4397 goto err_close_adapter;
4398 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004399 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004400
4401 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4402 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4403 if ( NULL == pP2pAdapter )
4404 {
4405 hddLog(VOS_TRACE_LEVEL_FATAL,
4406 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004407 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004408 goto err_close_adapter;
4409 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004410#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004411 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004412#ifdef WLAN_SOFTAP_FEATURE
4413 }
4414#endif
4415
4416 if( pAdapter == NULL )
4417 {
4418 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
4419#ifdef ANI_BUS_TYPE_SDIO
4420 goto err_balstop;
4421#else
Jeff Johnson546a5c12013-02-15 10:11:20 -08004422 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004423#endif
4424 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004425
Jeff Johnson295189b2012-06-20 16:38:30 -07004426#ifdef WLAN_BTAMP_FEATURE
4427 vStatus = WLANBAP_Open(pVosContext);
4428 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4429 {
4430 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4431 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004432 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004433 }
4434
4435 vStatus = BSL_Init(pVosContext);
4436 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4437 {
4438 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4439 "%s: Failed to Init BSL",__func__);
4440 goto err_bap_close;
4441 }
4442 vStatus = WLANBAP_Start(pVosContext);
4443 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4444 {
4445 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4446 "%s: Failed to start TL",__func__);
4447 goto err_bap_close;
4448 }
4449
4450 pConfig = pHddCtx->cfg_ini;
4451 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4452 status = WLANBAP_SetConfig(&btAmpConfig);
4453
4454#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004455
Jeff Johnson295189b2012-06-20 16:38:30 -07004456#ifdef FEATURE_WLAN_SCAN_PNO
4457 /*SME must send channel update configuration to RIVA*/
4458 sme_UpdateChannelConfig(pHddCtx->hHal);
4459#endif
4460
4461#ifdef FEATURE_WLAN_INTEGRATED_SOC
4462 /* Register with platform driver as client for Suspend/Resume */
4463 status = hddRegisterPmOps(pHddCtx);
4464 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4465 {
4466 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4467#ifdef WLAN_BTAMP_FEATURE
4468 goto err_bap_stop;
4469#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004470 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004471#endif //WLAN_BTAMP_FEATURE
4472 }
4473
4474 /* Register TM level change handler function to the platform */
4475 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4476 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4477 {
4478 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4479 goto err_unregister_pmops;
4480 }
4481#endif
4482
4483 /* register for riva power on lock to platform driver */
4484 if (req_riva_power_on_lock("wlan"))
4485 {
4486 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4487 __func__);
4488 goto err_unregister_pmops;
4489 }
4490
Jeff Johnson295189b2012-06-20 16:38:30 -07004491 // register net device notifier for device change notification
4492 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4493
4494 if(ret < 0)
4495 {
4496 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4497 goto err_free_power_on_lock;
4498 }
4499
4500 //Initialize the nlink service
4501 if(nl_srv_init() != 0)
4502 {
4503 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4504 goto err_reg_netdev;
4505 }
4506
4507 //Initialize the BTC service
4508 if(btc_activate_service(pHddCtx) != 0)
4509 {
4510 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4511 goto err_nl_srv;
4512 }
4513
4514#ifdef PTT_SOCK_SVC_ENABLE
4515 //Initialize the PTT service
4516 if(ptt_sock_activate_svc(pHddCtx) != 0)
4517 {
4518 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4519 goto err_nl_srv;
4520 }
4521#endif
4522
Jeff Johnson295189b2012-06-20 16:38:30 -07004523 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004524#ifdef CONFIG_CFG80211
4525#ifdef WLAN_SOFTAP_FEATURE
4526 if (VOS_STA_SAP_MODE != hdd_get_conparam())
4527#endif
4528 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004529 /* Action frame registered in one adapter which will
4530 * applicable to all interfaces
4531 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004532 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004533 }
4534#endif
4535
4536 mutex_init(&pHddCtx->sap_lock);
4537
4538 pHddCtx->isLoadUnloadInProgress = FALSE;
4539
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004540#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004541#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4542 /* Initialize the wake lcok */
4543 wake_lock_init(&pHddCtx->rx_wake_lock,
4544 WAKE_LOCK_SUSPEND,
4545 "qcom_rx_wakelock");
4546#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004547 /* Initialize the wake lcok */
4548 wake_lock_init(&pHddCtx->sap_wake_lock,
4549 WAKE_LOCK_SUSPEND,
4550 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004551#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004552
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004553 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4554 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004555
4556 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4557 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004558
4559 // Initialize the restart logic
4560 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304561
4562#ifdef FEATURE_WLAN_TDLS
Hoonki Lee387663d2013-02-05 18:08:43 -08004563 if(0 != wlan_hdd_tdls_init(pAdapter->dev))
4564 {
4565 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_tdls_init failed",__func__);
4566 goto err_nl_srv;
4567 }
Chilam NG571c65a2013-01-19 12:27:36 +05304568#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004569
4570 goto success;
4571
4572err_nl_srv:
4573 nl_srv_exit();
4574
4575err_reg_netdev:
4576 unregister_netdevice_notifier(&hdd_netdev_notifier);
4577
4578err_free_power_on_lock:
4579 free_riva_power_on_lock("wlan");
4580
4581err_unregister_pmops:
4582 hddDevTmUnregisterNotifyCallback(pHddCtx);
4583 hddDeregisterPmOps(pHddCtx);
4584
4585#ifdef WLAN_BTAMP_FEATURE
4586err_bap_stop:
4587 WLANBAP_Stop(pVosContext);
4588#endif
4589
4590#ifdef WLAN_BTAMP_FEATURE
4591err_bap_close:
4592 WLANBAP_Close(pVosContext);
4593#endif
4594
Jeff Johnson295189b2012-06-20 16:38:30 -07004595err_close_adapter:
4596 hdd_close_all_adapters( pHddCtx );
4597
4598err_vosstop:
4599 vos_stop(pVosContext);
4600
4601err_vosclose:
4602 status = vos_sched_close( pVosContext );
4603 if (!VOS_IS_STATUS_SUCCESS(status)) {
4604 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4605 "%s: Failed to close VOSS Scheduler", __func__);
4606 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4607 }
4608 vos_close(pVosContext );
4609
4610err_balstop:
4611#ifdef ANI_BUS_TYPE_SDIO
4612#ifndef ANI_MANF_DIAG
4613 wlan_hdd_enable_deepsleep(pHddCtx->pvosContext);
4614#endif
4615
4616 WLANBAL_Stop(pHddCtx->pvosContext);
4617 WLANBAL_SuspendChip(pHddCtx->pvosContext);
4618#endif
4619
4620#ifdef ANI_BUS_TYPE_SDIO
4621err_salstop:
4622 WLANSAL_Stop(pHddCtx->pvosContext);
4623
Jeff Johnson295189b2012-06-20 16:38:30 -07004624err_clkvote:
Jeff Johnson546a5c12013-02-15 10:11:20 -08004625#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004626 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4627
4628#ifdef ANI_BUS_TYPE_SDIO
4629err_balclose:
4630 WLANBAL_Close(pHddCtx->pvosContext);
4631#endif // ANI_BUS_TYPE_SDIO
4632
4633err_wdclose:
4634 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4635 vos_watchdog_close(pVosContext);
4636
4637#ifdef CONFIG_CFG80211
4638err_wiphy_reg:
4639 wiphy_unregister(wiphy) ;
4640#endif
4641
4642err_config:
4643 kfree(pHddCtx->cfg_ini);
4644 pHddCtx->cfg_ini= NULL;
4645
4646err_free_hdd_context:
4647 hdd_allow_suspend();
4648#ifdef CONFIG_CFG80211
4649 wiphy_free(wiphy) ;
4650 //kfree(wdev) ;
4651#else
4652 vos_mem_free( pHddCtx );
4653#endif
4654 VOS_BUG(1);
4655
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004656 if (hdd_is_ssr_required())
4657 {
4658 /* WDI timeout had happened during load, so SSR is needed here */
4659 subsystem_restart("wcnss");
4660 msleep(5000);
4661 }
4662 hdd_set_ssr_required (VOS_FALSE);
4663
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004664 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004665
4666success:
4667 EXIT();
4668 return 0;
4669}
4670
4671/**---------------------------------------------------------------------------
4672
Jeff Johnson32d95a32012-09-10 13:15:23 -07004673 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004674
Jeff Johnson32d95a32012-09-10 13:15:23 -07004675 This is the driver entry point - called in different timeline depending
4676 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004677
4678 \param - None
4679
4680 \return - 0 for success, non zero for failure
4681
4682 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004683static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004684{
4685 VOS_STATUS status;
4686 v_CONTEXT_t pVosContext = NULL;
4687#ifdef ANI_BUS_TYPE_SDIO
4688 struct sdio_func *sdio_func_dev = NULL;
4689 unsigned int attempts = 0;
4690#endif // ANI_BUS_TYPE_SDIO
4691 struct device *dev = NULL;
4692 int ret_status = 0;
4693
4694 ENTER();
4695
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004696#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004697 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004698#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004699
4700 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4701 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4702
4703 //Power Up Libra WLAN card first if not already powered up
4704 status = vos_chipPowerUp(NULL,NULL,NULL);
4705 if (!VOS_IS_STATUS_SUCCESS(status))
4706 {
4707 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4708 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004709 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004710 }
4711
4712#ifdef ANI_BUS_TYPE_SDIO
4713 //SDIO Polling should be turned on for card detection. When using Android Wi-Fi GUI
4714 //users need not trigger SDIO polling explicitly. However when loading drivers via
4715 //command line (Adb shell), users must turn on SDIO polling prior to loading WLAN.
4716 do {
4717 sdio_func_dev = libra_getsdio_funcdev();
4718 if (NULL == sdio_func_dev) {
4719 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
4720 attempts++;
4721 }
4722 else {
4723 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
4724 dev = &sdio_func_dev->dev;
4725 break;
4726 }
4727
4728 if(attempts == 7)
4729 break;
4730
4731 msleep(250);
4732
4733 }while (attempts < 7);
4734
4735 //Retry to detect the card again by Powering Down the chip and Power up the chip
4736 //again. This retry is done to recover from CRC Error
4737 if (NULL == sdio_func_dev) {
4738
4739 attempts = 0;
4740
4741 //Vote off any PMIC voltage supplies
4742 vos_chipPowerDown(NULL, NULL, NULL);
4743
4744 msleep(1000);
4745
4746 //Power Up Libra WLAN card first if not already powered up
4747 status = vos_chipPowerUp(NULL,NULL,NULL);
4748 if (!VOS_IS_STATUS_SUCCESS(status))
4749 {
4750 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
4751 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004752 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004753 }
4754
4755 do {
4756 sdio_func_dev = libra_getsdio_funcdev();
4757 if (NULL == sdio_func_dev) {
4758 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
4759 attempts++;
4760 }
4761 else {
4762 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
4763 dev = &sdio_func_dev->dev;
4764 break;
4765 }
4766
4767 if(attempts == 2)
4768 break;
4769
4770 msleep(1000);
4771
4772 }while (attempts < 3);
4773 }
4774
4775#endif // ANI_BUS_TYPE_SDIO
4776
4777#ifdef ANI_BUS_TYPE_PCI
4778
4779 dev = wcnss_wlan_get_device();
4780
4781#endif // ANI_BUS_TYPE_PCI
4782
4783#ifdef ANI_BUS_TYPE_PLATFORM
4784 dev = wcnss_wlan_get_device();
4785#endif // ANI_BUS_TYPE_PLATFORM
4786
4787
4788 do {
4789 if (NULL == dev) {
4790 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4791 ret_status = -1;
4792 break;
4793 }
4794
4795#ifdef MEMORY_DEBUG
4796 vos_mem_init();
4797#endif
4798
4799#ifdef TIMER_MANAGER
4800 vos_timer_manager_init();
4801#endif
4802
4803 /* Preopen VOSS so that it is ready to start at least SAL */
4804 status = vos_preOpen(&pVosContext);
4805
4806 if (!VOS_IS_STATUS_SUCCESS(status))
4807 {
4808 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4809 ret_status = -1;
4810 break;
4811 }
4812
4813#ifdef ANI_BUS_TYPE_SDIO
4814 /* Now Open SAL */
4815 status = WLANSAL_Open(pVosContext, 0);
4816
4817 if(!VOS_IS_STATUS_SUCCESS(status))
4818 {
4819 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to open SAL", __func__);
4820
4821 /* If unable to open, cleanup and return failure */
4822 vos_preClose( &pVosContext );
4823 ret_status = -1;
4824 break;
4825 }
4826#endif // ANI_BUS_TYPE_SDIO
4827
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004828#ifndef MODULE
4829 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4830 */
4831 hdd_set_conparam((v_UINT_t)con_mode);
4832#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004833
4834 // Call our main init function
4835 if(hdd_wlan_startup(dev)) {
4836 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
4837 __func__);
4838#ifdef ANI_BUS_TYPE_SDIO
4839 WLANSAL_Close(pVosContext);
4840#endif // ANI_BUS_TYPE_SDIO
4841 vos_preClose( &pVosContext );
4842 ret_status = -1;
4843 break;
4844 }
4845
4846 /* Cancel the vote for XO Core ON
4847 * This is done here for safety purposes in case we re-initialize without turning
4848 * it OFF in any error scenario.
4849 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004850 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004851 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004852 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004853 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4854 {
4855 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4856 " Power consumed will be high\n");
4857 }
4858 } while (0);
4859
4860 if (0 != ret_status)
4861 {
4862 //Assert Deep sleep signal now to put Libra HW in lowest power state
4863 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4864 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4865
4866 //Vote off any PMIC voltage supplies
4867 vos_chipPowerDown(NULL, NULL, NULL);
4868#ifdef TIMER_MANAGER
4869 vos_timer_exit();
4870#endif
4871#ifdef MEMORY_DEBUG
4872 vos_mem_exit();
4873#endif
4874
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004875#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004877#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004878 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4879 }
4880 else
4881 {
4882 //Send WLAN UP indication to Nlink Service
4883 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4884
4885 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4886
4887 }
4888
4889 EXIT();
4890
4891 return ret_status;
4892}
4893
Jeff Johnson32d95a32012-09-10 13:15:23 -07004894/**---------------------------------------------------------------------------
4895
4896 \brief hdd_module_init() - Init Function
4897
4898 This is the driver entry point (invoked when module is loaded using insmod)
4899
4900 \param - None
4901
4902 \return - 0 for success, non zero for failure
4903
4904 --------------------------------------------------------------------------*/
4905#ifdef MODULE
4906static int __init hdd_module_init ( void)
4907{
4908 return hdd_driver_init();
4909}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004910#else /* #ifdef MODULE */
4911static int __init hdd_module_init ( void)
4912{
4913 /* Driver initialization is delayed to fwpath_changed_handler */
4914 return 0;
4915}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004916#endif /* #ifdef MODULE */
4917
Jeff Johnson295189b2012-06-20 16:38:30 -07004918
4919/**---------------------------------------------------------------------------
4920
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004921 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004922
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004923 This is the driver exit point (invoked when module is unloaded using rmmod
4924 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004925
4926 \param - None
4927
4928 \return - None
4929
4930 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004931static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004932{
4933 hdd_context_t *pHddCtx = NULL;
4934 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004935
4936 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4937
4938 //Get the global vos context
4939 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4940
4941 if(!pVosContext)
4942 {
4943 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4944 goto done;
4945 }
4946
4947 //Get the HDD context.
4948 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4949
4950 if(!pHddCtx)
4951 {
4952 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
4953 }
4954 else
4955 {
Jeff Johnsone7245742012-09-05 17:12:55 -07004956 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07004957 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07004958 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
4959 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07004960 }
4961
4962 pHddCtx->isLoadUnloadInProgress = TRUE;
4963 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4964
4965 //Do all the cleanup before deregistering the driver
4966 hdd_wlan_exit(pHddCtx);
4967 }
4968
4969#ifdef ANI_BUS_TYPE_SDIO
4970 WLANSAL_Close(pVosContext);
4971#endif // ANI_BUS_TYPE_SDIO
4972
4973 vos_preClose( &pVosContext );
4974
4975#ifdef TIMER_MANAGER
4976 vos_timer_exit();
4977#endif
4978#ifdef MEMORY_DEBUG
4979 vos_mem_exit();
4980#endif
4981
4982done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004983#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004984 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004985#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004986 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
4987}
4988
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004989/**---------------------------------------------------------------------------
4990
4991 \brief hdd_module_exit() - Exit function
4992
4993 This is the driver exit point (invoked when module is unloaded using rmmod)
4994
4995 \param - None
4996
4997 \return - None
4998
4999 --------------------------------------------------------------------------*/
5000static void __exit hdd_module_exit(void)
5001{
5002 hdd_driver_exit();
5003}
5004
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005005#ifdef MODULE
5006static int fwpath_changed_handler(const char *kmessage,
5007 struct kernel_param *kp)
5008{
5009 /* nothing to do when driver is DLKM */
5010 return 0;
5011}
5012
5013static int con_mode_handler(const char *kmessage,
5014 struct kernel_param *kp)
5015{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005016 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005017}
5018#else /* #ifdef MODULE */
5019/**---------------------------------------------------------------------------
5020
5021 \brief fwpath_changed_handler() - Handler Function
5022
5023 This is the driver entry point
5024 - delayed driver initialization when driver is statically linked
5025 - invoked when module parameter fwpath is modified from userpspace to signal
5026 initializing the WLAN driver
5027
5028 \return - 0 for success, non zero for failure
5029
5030 --------------------------------------------------------------------------*/
5031static int fwpath_changed_handler(const char *kmessage,
5032 struct kernel_param *kp)
5033{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005034 int ret_status;
5035
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005036 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005037 ret_status = hdd_driver_init();
5038 wlan_hdd_inited = ret_status ? 0 : 1;
5039 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005040 }
5041
5042 hdd_driver_exit();
5043
5044 msleep(200);
5045
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005046 ret_status = hdd_driver_init();
5047 wlan_hdd_inited = ret_status ? 0 : 1;
5048 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005049}
5050
Jeff Johnson295189b2012-06-20 16:38:30 -07005051/**---------------------------------------------------------------------------
5052
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005053 \brief con_mode_handler() -
5054
5055 Handler function for module param con_mode when it is changed by userspace
5056 Dynamically linked - do nothing
5057 Statically linked - exit and init driver, as in rmmod and insmod
5058
5059 \param -
5060
5061 \return -
5062
5063 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005064static int con_mode_handler(const char *kmessage,
5065 struct kernel_param *kp)
5066{
5067 int ret = param_set_int(kmessage, kp);
5068
5069 if (ret)
5070 return ret;
5071
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005072 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005073}
5074#endif /* #ifdef MODULE */
5075
5076/**---------------------------------------------------------------------------
5077
Jeff Johnson295189b2012-06-20 16:38:30 -07005078 \brief hdd_get_conparam() -
5079
5080 This is the driver exit point (invoked when module is unloaded using rmmod)
5081
5082 \param - None
5083
5084 \return - tVOS_CON_MODE
5085
5086 --------------------------------------------------------------------------*/
5087tVOS_CON_MODE hdd_get_conparam ( void )
5088{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005089#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005090 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005091#else
5092 return (tVOS_CON_MODE)curr_con_mode;
5093#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005094}
5095void hdd_set_conparam ( v_UINT_t newParam )
5096{
5097 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005098#ifndef MODULE
5099 curr_con_mode = con_mode;
5100#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005101}
5102/**---------------------------------------------------------------------------
5103
5104 \brief hdd_softap_sta_deauth() - function
5105
5106 This to take counter measure to handle deauth req from HDD
5107
5108 \param - pAdapter - Pointer to the HDD
5109
5110 \param - enable - boolean value
5111
5112 \return - None
5113
5114 --------------------------------------------------------------------------*/
5115
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005116VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005117{
Jeff Johnson295189b2012-06-20 16:38:30 -07005118 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005119 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005120#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
5121 tHalHandle hHalHandle;
5122#endif
5123
5124 ENTER();
5125
5126 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5127
5128 //Ignore request to deauth bcmc station
5129 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005130 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005131
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005132 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005133
5134 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005135 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005136}
5137
5138/**---------------------------------------------------------------------------
5139
5140 \brief hdd_softap_sta_disassoc() - function
5141
5142 This to take counter measure to handle deauth req from HDD
5143
5144 \param - pAdapter - Pointer to the HDD
5145
5146 \param - enable - boolean value
5147
5148 \return - None
5149
5150 --------------------------------------------------------------------------*/
5151
5152void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5153{
5154 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5155
5156 ENTER();
5157
5158 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5159
5160 //Ignore request to disassoc bcmc station
5161 if( pDestMacAddress[0] & 0x1 )
5162 return;
5163
5164 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5165}
5166
5167void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5168{
5169 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5170
5171 ENTER();
5172
5173 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5174
5175 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5176}
5177
Jeff Johnson295189b2012-06-20 16:38:30 -07005178/**---------------------------------------------------------------------------
5179 *
5180 * \brief hdd_get__concurrency_mode() -
5181 *
5182 *
5183 * \param - None
5184 *
5185 * \return - CONCURRENCY MODE
5186 *
5187 * --------------------------------------------------------------------------*/
5188tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5189{
5190 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5191 hdd_context_t *pHddCtx;
5192
5193 if (NULL != pVosContext)
5194 {
5195 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5196 if (NULL != pHddCtx)
5197 {
5198 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5199 }
5200 }
5201
5202 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005203 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005204 return VOS_STA;
5205}
5206
5207/* Decide whether to allow/not the apps power collapse.
5208 * Allow apps power collapse if we are in connected state.
5209 * if not, allow only if we are in IMPS */
5210v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5211{
5212 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005213 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005214 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5215 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5216 hdd_adapter_t *pAdapter = NULL;
5217 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005218 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005219
5220#ifdef WLAN_SOFTAP_FEATURE
5221 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5222 return TRUE;
5223#endif
5224
Yathish9f22e662012-12-10 14:21:35 -08005225 concurrent_state = hdd_get_concurrency_mode();
5226
5227#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5228 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5229 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5230 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5231 return TRUE;
5232#endif
5233
Jeff Johnson295189b2012-06-20 16:38:30 -07005234 /*loop through all adapters. TBD fix for Concurrency */
5235 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5236 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5237 {
5238 pAdapter = pAdapterNode->pAdapter;
5239 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5240 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5241 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005242 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005243 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005244 && pmcState != STOPPED && pmcState != STANDBY)) ||
5245 (eANI_BOOLEAN_TRUE == scanRspPending))
Jeff Johnson295189b2012-06-20 16:38:30 -07005246 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005247 hddLog( LOGE, "%s: do not allow APPS power collapse-"
5248 "pmcState = %d scanRspPending = %d",
5249 __func__, pmcState, scanRspPending );
Jeff Johnson295189b2012-06-20 16:38:30 -07005250 return FALSE;
5251 }
5252 }
5253 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5254 pAdapterNode = pNext;
5255 }
5256 return TRUE;
5257}
5258
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005259/* Decides whether to send suspend notification to Riva
5260 * if any adapter is in BMPS; then it is required */
5261v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5262{
5263 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5264 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5265
5266 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5267 {
5268 return TRUE;
5269 }
5270 return FALSE;
5271}
5272
Jeff Johnson295189b2012-06-20 16:38:30 -07005273void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5274{
5275 switch(mode)
5276 {
5277 case WLAN_HDD_INFRA_STATION:
5278#ifdef WLAN_FEATURE_P2P
5279 case WLAN_HDD_P2P_CLIENT:
5280 case WLAN_HDD_P2P_GO:
5281#endif
5282 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07005283 pHddCtx->concurrency_mode |= (1 << mode);
5284 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005285 break;
5286 default:
5287 break;
5288
5289 }
5290 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5291 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5292}
5293
5294
5295void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5296{
5297 switch(mode)
5298 {
5299 case WLAN_HDD_INFRA_STATION:
5300#ifdef WLAN_FEATURE_P2P
5301 case WLAN_HDD_P2P_CLIENT:
5302 case WLAN_HDD_P2P_GO:
5303#endif
5304 case WLAN_HDD_SOFTAP:
5305 pHddCtx->no_of_sessions[mode]--;
5306 if (!(pHddCtx->no_of_sessions[mode]))
5307 pHddCtx->concurrency_mode &= (~(1 << mode));
5308 break;
5309 default:
5310 break;
5311 }
5312 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5313 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5314}
5315
Jeff Johnsone7245742012-09-05 17:12:55 -07005316/**---------------------------------------------------------------------------
5317 *
5318 * \brief wlan_hdd_restart_init
5319 *
5320 * This function initalizes restart timer/flag. An internal function.
5321 *
5322 * \param - pHddCtx
5323 *
5324 * \return - None
5325 *
5326 * --------------------------------------------------------------------------*/
5327
5328static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5329{
5330 /* Initialize */
5331 pHddCtx->hdd_restart_retries = 0;
5332 atomic_set(&pHddCtx->isRestartInProgress, 0);
5333 vos_timer_init(&pHddCtx->hdd_restart_timer,
5334 VOS_TIMER_TYPE_SW,
5335 wlan_hdd_restart_timer_cb,
5336 pHddCtx);
5337}
5338/**---------------------------------------------------------------------------
5339 *
5340 * \brief wlan_hdd_restart_deinit
5341 *
5342 * This function cleans up the resources used. An internal function.
5343 *
5344 * \param - pHddCtx
5345 *
5346 * \return - None
5347 *
5348 * --------------------------------------------------------------------------*/
5349
5350static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5351{
5352
5353 VOS_STATUS vos_status;
5354 /* Block any further calls */
5355 atomic_set(&pHddCtx->isRestartInProgress, 1);
5356 /* Cleanup */
5357 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5358 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005359 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005360 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5361 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005362 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005363
5364}
5365
5366/**---------------------------------------------------------------------------
5367 *
5368 * \brief wlan_hdd_framework_restart
5369 *
5370 * This function uses a cfg80211 API to start a framework initiated WLAN
5371 * driver module unload/load.
5372 *
5373 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5374 *
5375 *
5376 * \param - pHddCtx
5377 *
5378 * \return - VOS_STATUS_SUCCESS: Success
5379 * VOS_STATUS_E_EMPTY: Adapter is Empty
5380 * VOS_STATUS_E_NOMEM: No memory
5381
5382 * --------------------------------------------------------------------------*/
5383
5384static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5385{
5386 VOS_STATUS status = VOS_STATUS_SUCCESS;
5387 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5388 int len = (sizeof (struct ieee80211_mgmt));
5389 struct ieee80211_mgmt *mgmt = NULL;
5390
5391 /* Prepare the DEAUTH managment frame with reason code */
5392 mgmt = kzalloc(len, GFP_KERNEL);
5393 if(mgmt == NULL)
5394 {
5395 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005396 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005397 return VOS_STATUS_E_NOMEM;
5398 }
5399 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5400
5401 /* Iterate over all adapters/devices */
5402 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5403 do
5404 {
5405 if( (status == VOS_STATUS_SUCCESS) &&
5406 pAdapterNode &&
5407 pAdapterNode->pAdapter)
5408 {
5409 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5410 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5411 pAdapterNode->pAdapter->dev->name,
5412 pAdapterNode->pAdapter->device_mode,
5413 pHddCtx->hdd_restart_retries + 1);
5414 /*
5415 * CFG80211 event to restart the driver
5416 *
5417 * 'cfg80211_send_unprot_deauth' sends a
5418 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5419 * of SME(Linux Kernel) state machine.
5420 *
5421 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5422 * the driver.
5423 *
5424 */
5425
5426 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5427 }
5428 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5429 pAdapterNode = pNext;
5430 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5431
5432
5433 /* Free the allocated management frame */
5434 kfree(mgmt);
5435
5436 /* Retry until we unload or reach max count */
5437 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5438 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5439
5440 return status;
5441
5442}
5443/**---------------------------------------------------------------------------
5444 *
5445 * \brief wlan_hdd_restart_timer_cb
5446 *
5447 * Restart timer callback. An internal function.
5448 *
5449 * \param - User data:
5450 *
5451 * \return - None
5452 *
5453 * --------------------------------------------------------------------------*/
5454
5455void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5456{
5457 hdd_context_t *pHddCtx = usrDataForCallback;
5458 wlan_hdd_framework_restart(pHddCtx);
5459 return;
5460
5461}
5462
5463
5464/**---------------------------------------------------------------------------
5465 *
5466 * \brief wlan_hdd_restart_driver
5467 *
5468 * This function sends an event to supplicant to restart the WLAN driver.
5469 *
5470 * This function is called from vos_wlanRestart.
5471 *
5472 * \param - pHddCtx
5473 *
5474 * \return - VOS_STATUS_SUCCESS: Success
5475 * VOS_STATUS_E_EMPTY: Adapter is Empty
5476 * VOS_STATUS_E_ALREADY: Request already in progress
5477
5478 * --------------------------------------------------------------------------*/
5479VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5480{
5481 VOS_STATUS status = VOS_STATUS_SUCCESS;
5482
5483 /* A tight check to make sure reentrancy */
5484 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5485 {
5486 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5487 "%s: WLAN restart is already in progress", __func__);
5488
5489 return VOS_STATUS_E_ALREADY;
5490 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005491 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005492 * the reset interrupt. If it is DLKM, then use restart API
5493 */
5494#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005495 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005496#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005497#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005498 wcnss_reset_intr();
5499#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005500#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005501
Jeff Johnsone7245742012-09-05 17:12:55 -07005502 return status;
5503}
5504
5505
Jeff Johnson295189b2012-06-20 16:38:30 -07005506//Register the module init/exit functions
5507module_init(hdd_module_init);
5508module_exit(hdd_module_exit);
5509
5510MODULE_LICENSE("Dual BSD/GPL");
5511MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5512MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5513
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005514module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5515 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005516
5517module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5518 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);