blob: eabb32dab412785bb05abb16dcc40ae98038cca4 [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
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08002058void hdd_set_pwrparams(hdd_context_t *pHddCtx)
2059{
2060 tSirSetPowerParamsReq powerRequest = { 0 };
2061
2062 powerRequest.uIgnoreDTIM = 1;
2063
2064 if (pHddCtx->cfg_ini->enableModulatedDTIM)
2065 {
2066 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
2067 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2068 }
2069 else
2070 {
2071 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
2072 }
2073
2074 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
2075 *specified during Enter/Exit BMPS when LCD off*/
2076 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2077 NULL, eANI_BOOLEAN_FALSE);
2078 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2079 NULL, eANI_BOOLEAN_FALSE);
2080
2081 /* switch to the DTIM specified in cfg.ini */
2082 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2083 "Switch to DTIM%d", powerRequest.uListenInterval);
2084 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2085
2086}
2087
2088void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
2089{
2090 /*Switch back to DTIM 1*/
2091 tSirSetPowerParamsReq powerRequest = { 0 };
2092
2093 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
2094 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
2095
2096 /* Update ignoreDTIM and ListedInterval in CFG with default values */
2097 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
2098 NULL, eANI_BOOLEAN_FALSE);
2099 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
2100 NULL, eANI_BOOLEAN_FALSE);
2101
2102 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2103 "Switch to DTIM%d",powerRequest.uListenInterval);
2104 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
2105
2106}
2107
Jeff Johnson295189b2012-06-20 16:38:30 -07002108VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
2109{
2110 VOS_STATUS status = VOS_STATUS_SUCCESS;
2111
2112 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2113 {
2114 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2115 }
2116
2117 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2118 {
2119 sme_StartAutoBmpsTimer(pHddCtx->hHal);
2120 }
2121
2122 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2123 {
2124 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2125 }
2126
2127 return status;
2128}
2129
2130VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
2131{
2132 hdd_adapter_t *pAdapter = NULL;
2133 eHalStatus halStatus;
2134 VOS_STATUS status = VOS_STATUS_E_INVAL;
2135 v_BOOL_t disableBmps = FALSE;
2136 v_BOOL_t disableImps = FALSE;
2137
2138 switch(session_type)
2139 {
2140 case WLAN_HDD_INFRA_STATION:
2141 case WLAN_HDD_SOFTAP:
2142#ifdef WLAN_FEATURE_P2P
2143 case WLAN_HDD_P2P_CLIENT:
2144 case WLAN_HDD_P2P_GO:
2145#endif
2146 //Exit BMPS -> Is Sta/P2P Client is already connected
2147 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
2148 if((NULL != pAdapter)&&
2149 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2150 {
2151 disableBmps = TRUE;
2152 }
2153
2154 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
2155 if((NULL != pAdapter)&&
2156 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
2157 {
2158 disableBmps = TRUE;
2159 }
2160
2161 //Exit both Bmps and Imps incase of Go/SAP Mode
2162 if((WLAN_HDD_SOFTAP == session_type) ||
2163 (WLAN_HDD_P2P_GO == session_type))
2164 {
2165 disableBmps = TRUE;
2166 disableImps = TRUE;
2167 }
2168
2169 if(TRUE == disableImps)
2170 {
2171 if (pHddCtx->cfg_ini->fIsImpsEnabled)
2172 {
2173 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
2174 }
2175 }
2176
2177 if(TRUE == disableBmps)
2178 {
2179 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
2180 {
2181 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
2182
2183 if(eHAL_STATUS_SUCCESS != halStatus)
2184 {
2185 status = VOS_STATUS_E_FAILURE;
2186 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
2187 VOS_ASSERT(0);
2188 return status;
2189 }
2190 }
2191
2192 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
2193 {
2194 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
2195
2196 if(eHAL_STATUS_SUCCESS != halStatus)
2197 {
2198 status = VOS_STATUS_E_FAILURE;
2199 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
2200 VOS_ASSERT(0);
2201 return status;
2202 }
2203 }
2204 }
2205
2206 if((TRUE == disableBmps) ||
2207 (TRUE == disableImps))
2208 {
2209 /* Now, get the chip into Full Power now */
2210 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
2211 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
2212 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
2213
2214 if(halStatus != eHAL_STATUS_SUCCESS)
2215 {
2216 if(halStatus == eHAL_STATUS_PMC_PENDING)
2217 {
2218 //Block on a completion variable. Can't wait forever though
2219 wait_for_completion_interruptible_timeout(
2220 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
2221 }
2222 else
2223 {
2224 status = VOS_STATUS_E_FAILURE;
2225 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
2226 VOS_ASSERT(0);
2227 return status;
2228 }
2229 }
2230
2231 status = VOS_STATUS_SUCCESS;
2232 }
2233
2234 break;
2235 }
2236 return status;
2237}
2238
2239hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08002240 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07002241 tANI_U8 rtnl_held )
2242{
2243 hdd_adapter_t *pAdapter = NULL;
2244 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
2245 VOS_STATUS status = VOS_STATUS_E_FAILURE;
2246 VOS_STATUS exitbmpsStatus;
2247
2248 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
2249
2250 //Disable BMPS incase of Concurrency
2251 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
2252
2253 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
2254 {
2255 //Fail to Exit BMPS
2256 VOS_ASSERT(0);
2257 return NULL;
2258 }
2259
2260 switch(session_type)
2261 {
2262 case WLAN_HDD_INFRA_STATION:
2263#ifdef WLAN_FEATURE_P2P
2264 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002265 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002266#endif
2267 {
2268 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2269
2270 if( NULL == pAdapter )
2271 return NULL;
2272
2273#ifdef CONFIG_CFG80211
Jeff Johnsone7245742012-09-05 17:12:55 -07002274 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
2275 NL80211_IFTYPE_P2P_CLIENT:
2276 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07002277#endif
2278
Jeff Johnson295189b2012-06-20 16:38:30 -07002279 pAdapter->device_mode = session_type;
2280
2281 status = hdd_init_station_mode( pAdapter );
2282 if( VOS_STATUS_SUCCESS != status )
2283 goto err_free_netdev;
2284
2285 status = hdd_register_interface( pAdapter, rtnl_held );
2286 if( VOS_STATUS_SUCCESS != status )
2287 {
2288 hdd_deinit_adapter(pHddCtx, pAdapter);
2289 goto err_free_netdev;
2290 }
2291 //Stop the Interface TX queue.
2292 netif_tx_disable(pAdapter->dev);
2293 //netif_tx_disable(pWlanDev);
2294 netif_carrier_off(pAdapter->dev);
2295
2296 break;
2297 }
2298
2299#ifdef WLAN_FEATURE_P2P
2300 case WLAN_HDD_P2P_GO:
2301#endif
2302 case WLAN_HDD_SOFTAP:
2303 {
2304 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
2305 if( NULL == pAdapter )
2306 return NULL;
2307
2308#ifdef CONFIG_CFG80211
2309 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
2310 NL80211_IFTYPE_AP:
2311 NL80211_IFTYPE_P2P_GO;
2312#endif
2313 pAdapter->device_mode = session_type;
2314
2315 status = hdd_init_ap_mode(pAdapter);
2316 if( VOS_STATUS_SUCCESS != status )
2317 goto err_free_netdev;
2318
2319 status = hdd_register_hostapd( pAdapter, rtnl_held );
2320 if( VOS_STATUS_SUCCESS != status )
2321 {
2322 hdd_deinit_adapter(pHddCtx, pAdapter);
2323 goto err_free_netdev;
2324 }
2325
2326 netif_tx_disable(pAdapter->dev);
2327 netif_carrier_off(pAdapter->dev);
2328
2329 hdd_set_conparam( 1 );
2330 break;
2331 }
2332 case WLAN_HDD_MONITOR:
2333 {
2334#ifdef CONFIG_CFG80211
2335 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2336 if( NULL == pAdapter )
2337 return NULL;
2338
2339 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
2340 pAdapter->device_mode = session_type;
2341 status = hdd_register_interface( pAdapter, rtnl_held );
2342#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
2343 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
2344#else
2345 pAdapter->dev->open = hdd_mon_open;
2346 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
2347#endif
2348 hdd_init_tx_rx( pAdapter );
2349 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
2350 //Set adapter to be used for data tx. It will use either GO or softap.
2351 pAdapter->sessionCtx.monitor.pAdapterForTx =
2352 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
2353#ifdef WLAN_FEATURE_P2P
2354 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
2355 {
2356 pAdapter->sessionCtx.monitor.pAdapterForTx =
2357 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
2358 }
2359#endif
2360 /* This workqueue will be used to transmit management packet over
2361 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07002362 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
2363 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
2364 return NULL;
2365 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07002366
Jeff Johnson295189b2012-06-20 16:38:30 -07002367 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
2368 hdd_mon_tx_work_queue);
2369#endif
2370 }
2371 break;
2372#ifdef ANI_MANF_DIAG
2373 case WLAN_HDD_FTM:
2374 {
2375 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
2376
2377 if( NULL == pAdapter )
2378 return NULL;
2379 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
2380 * message while loading driver in FTM mode. */
2381 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
2382 pAdapter->device_mode = session_type;
2383 status = hdd_register_interface( pAdapter, rtnl_held );
2384 }
2385 break;
2386#endif
2387 default:
2388 {
2389 VOS_ASSERT(0);
2390 return NULL;
2391 }
2392 }
2393
2394
2395 if( VOS_STATUS_SUCCESS == status )
2396 {
2397 //Add it to the hdd's session list.
2398 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
2399 if( NULL == pHddAdapterNode )
2400 {
2401 status = VOS_STATUS_E_NOMEM;
2402 }
2403 else
2404 {
2405 pHddAdapterNode->pAdapter = pAdapter;
2406 status = hdd_add_adapter_back ( pHddCtx,
2407 pHddAdapterNode );
2408 }
2409 }
2410
2411 if( VOS_STATUS_SUCCESS != status )
2412 {
2413 if( NULL != pAdapter )
2414 {
2415 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
2416 pAdapter = NULL;
2417 }
2418 if( NULL != pHddAdapterNode )
2419 {
2420 vos_mem_free( pHddAdapterNode );
2421 }
2422
2423 goto resume_bmps;
2424 }
2425
2426 if(VOS_STATUS_SUCCESS == status)
2427 {
2428 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
2429
2430#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
2431 /* If there are concurrent session enable SW frame translation
2432 * for all registered STA
2433 * This is not required in case of PRIMA as HW frame translation
2434 * is disabled in PRIMA*/
2435 if (vos_concurrent_sessions_running())
2436 {
2437 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, TRUE);
2438 }
2439#endif
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07002440 //Initialize the WoWL service
2441 if(!hdd_init_wowl(pAdapter))
2442 {
2443 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
2444 goto err_free_netdev;
2445 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002446 }
Jeff Johnson295189b2012-06-20 16:38:30 -07002447 return pAdapter;
2448
2449err_free_netdev:
2450 free_netdev(pAdapter->dev);
2451 wlan_hdd_release_intf_addr( pHddCtx,
2452 pAdapter->macAddressCurrent.bytes );
2453
2454resume_bmps:
2455 //If bmps disabled enable it
2456 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
2457 {
2458 hdd_enable_bmps_imps(pHddCtx);
2459 }
2460 return NULL;
2461}
2462
2463VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
2464 tANI_U8 rtnl_held )
2465{
2466 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
2467 VOS_STATUS status;
2468
2469 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
2470 if( VOS_STATUS_SUCCESS != status )
2471 return status;
2472
2473 while ( pCurrent->pAdapter != pAdapter )
2474 {
2475 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
2476 if( VOS_STATUS_SUCCESS != status )
2477 break;
2478
2479 pCurrent = pNext;
2480 }
2481 pAdapterNode = pCurrent;
2482 if( VOS_STATUS_SUCCESS == status )
2483 {
2484 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
2485 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
2486 hdd_remove_adapter( pHddCtx, pAdapterNode );
2487 vos_mem_free( pAdapterNode );
2488
2489#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
2490 /* If there is no concurrent session disable SW frame translation
2491 * for all registered STA */
2492 /* This is not required in case of PRIMA as HW frame translation
2493 * is disabled in PRIMA*/
2494 if (!vos_concurrent_sessions_running())
2495 {
2496 WLANTL_ConfigureSwFrameTXXlationForAll(pHddCtx->pvosContext, FALSE);
2497 }
2498#endif
2499
2500 /* If there is a single session of STA/P2P client, re-enable BMPS */
2501 if ((!vos_concurrent_sessions_running()) &&
2502 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
2503 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
2504 {
2505 hdd_enable_bmps_imps(pHddCtx);
2506 }
2507
2508 return VOS_STATUS_SUCCESS;
2509 }
2510
2511 return VOS_STATUS_E_FAILURE;
2512}
2513
2514VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
2515{
2516 hdd_adapter_list_node_t *pHddAdapterNode;
2517 VOS_STATUS status;
2518
2519 ENTER();
2520
2521 do
2522 {
2523 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
2524 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
2525 {
2526 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
2527 vos_mem_free( pHddAdapterNode );
2528 }
2529 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
2530
2531 EXIT();
2532
2533 return VOS_STATUS_SUCCESS;
2534}
2535
2536void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
2537{
2538 v_U8_t addIE[1] = {0};
2539
2540 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2541 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
2542 eANI_BOOLEAN_FALSE) )
2543 {
2544 hddLog(LOGE,
2545 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
2546 }
2547
2548 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2549 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
2550 eANI_BOOLEAN_FALSE) )
2551 {
2552 hddLog(LOGE,
2553 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
2554 }
2555
2556 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
2557 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
2558 eANI_BOOLEAN_FALSE) )
2559 {
2560 hddLog(LOGE,
2561 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
2562 }
2563}
2564
2565VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
2566{
2567 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
2568 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2569 union iwreq_data wrqu;
2570
2571 ENTER();
2572
2573 switch(pAdapter->device_mode)
2574 {
2575 case WLAN_HDD_INFRA_STATION:
2576 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002577 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002578 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
2579 {
2580 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
2581 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2582 pAdapter->sessionId,
2583 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
2584 else
2585 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
2586 pAdapter->sessionId,
2587 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2588 //success implies disconnect command got queued up successfully
2589 if(halStatus == eHAL_STATUS_SUCCESS)
2590 {
2591 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
2592 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2593 }
2594 memset(&wrqu, '\0', sizeof(wrqu));
2595 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2596 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2597 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2598 }
2599 else
2600 {
2601 hdd_abort_mac_scan(pHddCtx);
2602 }
2603
2604 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
2605 {
2606 INIT_COMPLETION(pAdapter->session_close_comp_var);
2607 if (eHAL_STATUS_SUCCESS ==
2608 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
2609 hdd_smeCloseSessionCallback, pAdapter))
2610 {
2611 //Block on a completion variable. Can't wait forever though.
2612 wait_for_completion_interruptible_timeout(
2613 &pAdapter->session_close_comp_var,
2614 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
2615 }
2616 }
2617
2618 break;
2619
2620 case WLAN_HDD_SOFTAP:
2621 case WLAN_HDD_P2P_GO:
2622 //Any softap specific cleanup here...
2623 mutex_lock(&pHddCtx->sap_lock);
2624 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
2625 {
2626 VOS_STATUS status;
2627 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
2628
2629 //Stop Bss.
2630 status = WLANSAP_StopBss(pHddCtx->pvosContext);
2631 if (VOS_IS_STATUS_SUCCESS(status))
2632 {
2633 hdd_hostapd_state_t *pHostapdState =
2634 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
2635
2636 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
2637
2638 if (!VOS_IS_STATUS_SUCCESS(status))
2639 {
2640 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002641 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002642 }
2643 }
2644 else
2645 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002646 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002647 }
2648 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
2649
2650 if (eHAL_STATUS_FAILURE ==
2651 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
2652 0, NULL, eANI_BOOLEAN_FALSE))
2653 {
2654 hddLog(LOGE,
2655 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002656 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07002657 }
2658
2659 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
2660 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
2661 eANI_BOOLEAN_FALSE) )
2662 {
2663 hddLog(LOGE,
2664 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
2665 }
2666
2667 // Reset WNI_CFG_PROBE_RSP Flags
2668 wlan_hdd_reset_prob_rspies(pAdapter);
2669 kfree(pAdapter->sessionCtx.ap.beacon);
2670 pAdapter->sessionCtx.ap.beacon = NULL;
2671 }
2672 mutex_unlock(&pHddCtx->sap_lock);
2673 break;
2674 case WLAN_HDD_MONITOR:
2675 break;
2676 default:
2677 break;
2678 }
2679
2680 EXIT();
2681 return VOS_STATUS_SUCCESS;
2682}
2683
2684VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
2685{
2686 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2687 VOS_STATUS status;
2688 hdd_adapter_t *pAdapter;
2689
2690 ENTER();
2691
2692 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2693
2694 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2695 {
2696 pAdapter = pAdapterNode->pAdapter;
2697 netif_tx_disable(pAdapter->dev);
2698 netif_carrier_off(pAdapter->dev);
2699
2700 hdd_stop_adapter( pHddCtx, pAdapter );
2701
2702 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2703 pAdapterNode = pNext;
2704 }
2705
2706 EXIT();
2707
2708 return VOS_STATUS_SUCCESS;
2709}
2710
2711VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
2712{
2713 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2714 VOS_STATUS status;
2715 hdd_adapter_t *pAdapter;
2716
2717 ENTER();
2718
2719 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2720
2721 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2722 {
2723 pAdapter = pAdapterNode->pAdapter;
2724 netif_tx_disable(pAdapter->dev);
2725 netif_carrier_off(pAdapter->dev);
2726
2727 //Record whether STA is associated
2728 pAdapter->sessionCtx.station.bSendDisconnect =
2729 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ?
2730 VOS_TRUE : VOS_FALSE;
2731
2732 hdd_deinit_tx_rx(pAdapter);
2733 hdd_wmm_adapter_close(pAdapter);
2734
2735 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2736 pAdapterNode = pNext;
2737 }
2738
2739 EXIT();
2740
2741 return VOS_STATUS_SUCCESS;
2742}
2743
2744VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
2745{
2746 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2747 VOS_STATUS status;
2748 hdd_adapter_t *pAdapter;
2749 v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER;
2750
2751 ENTER();
2752
2753 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2754
2755 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2756 {
2757 pAdapter = pAdapterNode->pAdapter;
2758
2759 switch(pAdapter->device_mode)
2760 {
2761 case WLAN_HDD_INFRA_STATION:
2762 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07002763 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07002764 hdd_init_station_mode(pAdapter);
2765 /* Open the gates for HDD to receive Wext commands */
2766 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07002767 pHddCtx->scan_info.mScanPending = FALSE;
2768 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07002769
2770 //Trigger the initial scan
2771 hdd_wlan_initial_scan(pAdapter);
2772
2773 //Indicate disconnect event to supplicant if associated previously
2774 if(pAdapter->sessionCtx.station.bSendDisconnect)
2775 {
2776 union iwreq_data wrqu;
2777 memset(&wrqu, '\0', sizeof(wrqu));
2778 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
2779 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
2780 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
2781 pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE;
2782
2783#ifdef CONFIG_CFG80211
2784 /* indicate disconnected event to nl80211 */
2785 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
2786 NULL, 0, GFP_KERNEL);
2787#endif
2788 }
2789 break;
2790
2791 case WLAN_HDD_SOFTAP:
2792 /* softAP can handle SSR */
2793 break;
2794
2795 case WLAN_HDD_P2P_GO:
2796#ifdef CONFIG_CFG80211
2797 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send restart supplicant",
2798 __func__);
2799 /* event supplicant to restart */
2800 cfg80211_del_sta(pAdapter->dev,
2801 (const u8 *)&bcastMac.bytes[0], GFP_KERNEL);
2802#endif
2803 break;
2804
2805 case WLAN_HDD_MONITOR:
2806 /* monitor interface start */
2807 break;
2808 default:
2809 break;
2810 }
2811
2812 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2813 pAdapterNode = pNext;
2814 }
2815
2816 EXIT();
2817
2818 return VOS_STATUS_SUCCESS;
2819}
2820
2821VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
2822{
2823 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
2824 hdd_adapter_t *pAdapter;
2825 VOS_STATUS status;
2826 v_U32_t roamId;
2827
2828 ENTER();
2829
2830 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
2831
2832 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
2833 {
2834 pAdapter = pAdapterNode->pAdapter;
2835
2836 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
2837 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
2838 {
2839 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2840 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
2841
2842 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
2843 init_completion(&pAdapter->disconnect_comp_var);
2844 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
2845 eCSR_DISCONNECT_REASON_UNSPECIFIED);
2846
2847 wait_for_completion_interruptible_timeout(
2848 &pAdapter->disconnect_comp_var,
2849 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
2850
2851 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
2852 pHddCtx->isAmpAllowed = VOS_FALSE;
2853 sme_RoamConnect(pHddCtx->hHal,
2854 pAdapter->sessionId, &(pWextState->roamProfile),
2855 &roamId);
2856 }
2857
2858 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2859 pAdapterNode = pNext;
2860 }
2861
2862 EXIT();
2863
2864 return VOS_STATUS_SUCCESS;
2865}
2866
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002867bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07002868{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002869 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07002870}
2871
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002872/* Once SSR is disabled then it cannot be set. */
2873void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07002874{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07002875 if (HDD_SSR_DISABLED == isSsrRequired)
2876 return;
2877
Jeff Johnson295189b2012-06-20 16:38:30 -07002878 isSsrRequired = value;
2879}
2880
2881VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
2882 hdd_adapter_list_node_t** ppAdapterNode)
2883{
2884 VOS_STATUS status;
2885 spin_lock(&pHddCtx->hddAdapters.lock);
2886 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
2887 (hdd_list_node_t**) ppAdapterNode );
2888 spin_unlock(&pHddCtx->hddAdapters.lock);
2889 return status;
2890}
2891
2892VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
2893 hdd_adapter_list_node_t* pAdapterNode,
2894 hdd_adapter_list_node_t** pNextAdapterNode)
2895{
2896 VOS_STATUS status;
2897 spin_lock(&pHddCtx->hddAdapters.lock);
2898 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
2899 (hdd_list_node_t*) pAdapterNode,
2900 (hdd_list_node_t**)pNextAdapterNode );
2901
2902 spin_unlock(&pHddCtx->hddAdapters.lock);
2903 return status;
2904}
2905
2906VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
2907 hdd_adapter_list_node_t* pAdapterNode)
2908{
2909 VOS_STATUS status;
2910 spin_lock(&pHddCtx->hddAdapters.lock);
2911 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
2912 &pAdapterNode->node );
2913 spin_unlock(&pHddCtx->hddAdapters.lock);
2914 return status;
2915}
2916
2917VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
2918 hdd_adapter_list_node_t** ppAdapterNode)
2919{
2920 VOS_STATUS status;
2921 spin_lock(&pHddCtx->hddAdapters.lock);
2922 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
2923 (hdd_list_node_t**) ppAdapterNode );
2924 spin_unlock(&pHddCtx->hddAdapters.lock);
2925 return status;
2926}
2927
2928VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
2929 hdd_adapter_list_node_t* pAdapterNode)
2930{
2931 VOS_STATUS status;
2932 spin_lock(&pHddCtx->hddAdapters.lock);
2933 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
2934 (hdd_list_node_t*) pAdapterNode );
2935 spin_unlock(&pHddCtx->hddAdapters.lock);
2936 return status;
2937}
2938
2939VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
2940 hdd_adapter_list_node_t* pAdapterNode)
2941{
2942 VOS_STATUS status;
2943 spin_lock(&pHddCtx->hddAdapters.lock);
2944 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
2945 (hdd_list_node_t*) pAdapterNode );
2946 spin_unlock(&pHddCtx->hddAdapters.lock);
2947 return status;
2948}
2949
2950hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
2951 tSirMacAddr macAddr )
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 && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
2964 macAddr, sizeof(tSirMacAddr) ) )
2965 {
2966 return pAdapter;
2967 }
2968 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2969 pAdapterNode = pNext;
2970 }
2971
2972 return NULL;
2973
2974}
2975
2976hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
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 && !strncmp( pAdapter->dev->name, (const char *)name,
2989 IFNAMSIZ ) )
2990 {
2991 return pAdapter;
2992 }
2993 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
2994 pAdapterNode = pNext;
2995 }
2996
2997 return NULL;
2998
2999}
3000
3001hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
3002{
3003 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3004 hdd_adapter_t *pAdapter;
3005 VOS_STATUS status;
3006
3007 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3008
3009 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3010 {
3011 pAdapter = pAdapterNode->pAdapter;
3012
3013 if( pAdapter && (mode == pAdapter->device_mode) )
3014 {
3015 return pAdapter;
3016 }
3017 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3018 pAdapterNode = pNext;
3019 }
3020
3021 return NULL;
3022
3023}
3024
3025//Remove this function later
3026hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
3027{
3028 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3029 hdd_adapter_t *pAdapter;
3030 VOS_STATUS status;
3031
3032 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3033
3034 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3035 {
3036 pAdapter = pAdapterNode->pAdapter;
3037
3038 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
3039 {
3040 return pAdapter;
3041 }
3042
3043 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3044 pAdapterNode = pNext;
3045 }
3046
3047 return NULL;
3048
3049}
3050
3051#ifdef CONFIG_CFG80211
3052/**---------------------------------------------------------------------------
3053
3054 \brief hdd_set_monitor_tx_adapter() -
3055
3056 This API initializes the adapter to be used while transmitting on monitor
3057 adapter.
3058
3059 \param - pHddCtx - Pointer to the HDD context.
3060 pAdapter - Adapter that will used for TX. This can be NULL.
3061 \return - None.
3062 --------------------------------------------------------------------------*/
3063void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
3064{
3065 hdd_adapter_t *pMonAdapter;
3066
3067 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
3068
3069 if( NULL != pMonAdapter )
3070 {
3071 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
3072 }
3073}
3074#endif
3075/**---------------------------------------------------------------------------
3076
3077 \brief hdd_select_queue() -
3078
3079 This API returns the operating channel of the requested device mode
3080
3081 \param - pHddCtx - Pointer to the HDD context.
3082 - mode - Device mode for which operating channel is required
3083 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
3084 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
3085 \return - channel number. "0" id the requested device is not found OR it is not connected.
3086 --------------------------------------------------------------------------*/
3087v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
3088{
3089 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3090 VOS_STATUS status;
3091 hdd_adapter_t *pAdapter;
3092 v_U8_t operatingChannel = 0;
3093
3094 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3095
3096 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
3097 {
3098 pAdapter = pAdapterNode->pAdapter;
3099
3100 if( mode == pAdapter->device_mode )
3101 {
3102 switch(pAdapter->device_mode)
3103 {
3104 case WLAN_HDD_INFRA_STATION:
3105 case WLAN_HDD_P2P_CLIENT:
3106 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
3107 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
3108 break;
3109 case WLAN_HDD_SOFTAP:
3110 case WLAN_HDD_P2P_GO:
3111 /*softap connection info */
3112 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
3113 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
3114 break;
3115 default:
3116 break;
3117 }
3118
3119 break; //Found the device of interest. break the loop
3120 }
3121
3122 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3123 pAdapterNode = pNext;
3124 }
3125 return operatingChannel;
3126}
3127
3128#ifdef WLAN_FEATURE_PACKET_FILTERING
3129/**---------------------------------------------------------------------------
3130
3131 \brief hdd_set_multicast_list() -
3132
3133 This used to set the multicast address list.
3134
3135 \param - dev - Pointer to the WLAN device.
3136 - skb - Pointer to OS packet (sk_buff).
3137 \return - success/fail
3138
3139 --------------------------------------------------------------------------*/
3140static void hdd_set_multicast_list(struct net_device *dev)
3141{
3142 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07003143 int mc_count;
3144 int i = 0;
3145 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303146
3147 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07003148 {
3149 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303150 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003151 return;
3152 }
3153
3154 if (dev->flags & IFF_ALLMULTI)
3155 {
3156 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003157 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303158 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003159 }
3160 else
3161 {
3162 mc_count = netdev_mc_count(dev);
3163 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003164 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07003165 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
3166 {
3167 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003168 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303169 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07003170 return;
3171 }
3172
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303173 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07003174
3175 netdev_for_each_mc_addr(ha, dev) {
3176 if (i == mc_count)
3177 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303178 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
3179 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
3180 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07003181 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05303182 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07003183 i++;
3184 }
3185 }
3186 return;
3187}
3188#endif
3189
3190/**---------------------------------------------------------------------------
3191
3192 \brief hdd_select_queue() -
3193
3194 This function is registered with the Linux OS for network
3195 core to decide which queue to use first.
3196
3197 \param - dev - Pointer to the WLAN device.
3198 - skb - Pointer to OS packet (sk_buff).
3199 \return - ac, Queue Index/access category corresponding to UP in IP header
3200
3201 --------------------------------------------------------------------------*/
3202v_U16_t hdd_select_queue(struct net_device *dev,
3203 struct sk_buff *skb)
3204{
3205 return hdd_wmm_select_queue(dev, skb);
3206}
3207
3208
3209/**---------------------------------------------------------------------------
3210
3211 \brief hdd_wlan_initial_scan() -
3212
3213 This function triggers the initial scan
3214
3215 \param - pAdapter - Pointer to the HDD adapter.
3216
3217 --------------------------------------------------------------------------*/
3218void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
3219{
3220 tCsrScanRequest scanReq;
3221 tCsrChannelInfo channelInfo;
3222 eHalStatus halStatus;
3223 unsigned long scanId;
3224 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3225
3226 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
3227 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
3228 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
3229
3230 if(sme_Is11dSupported(pHddCtx->hHal))
3231 {
3232 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
3233 if ( HAL_STATUS_SUCCESS( halStatus ) )
3234 {
3235 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
3236 if( !scanReq.ChannelInfo.ChannelList )
3237 {
3238 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
3239 vos_mem_free(channelInfo.ChannelList);
3240 return;
3241 }
3242 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
3243 channelInfo.numOfChannels);
3244 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
3245 vos_mem_free(channelInfo.ChannelList);
3246 }
3247
3248 scanReq.scanType = eSIR_PASSIVE_SCAN;
3249 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
3250 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
3251 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
3252 }
3253 else
3254 {
3255 scanReq.scanType = eSIR_ACTIVE_SCAN;
3256 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
3257 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
3258 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
3259 }
3260
3261 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
3262 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3263 {
3264 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
3265 __func__, halStatus );
3266 }
3267
3268 if(sme_Is11dSupported(pHddCtx->hHal))
3269 vos_mem_free(scanReq.ChannelInfo.ChannelList);
3270}
3271
3272struct fullPowerContext
3273{
3274 struct completion completion;
3275 unsigned int magic;
3276};
3277#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
3278
3279/**---------------------------------------------------------------------------
3280
3281 \brief hdd_full_power_callback() - HDD full power callback function
3282
3283 This is the function invoked by SME to inform the result of a full power
3284 request issued by HDD
3285
3286 \param - callbackcontext - Pointer to cookie
3287 \param - status - result of request
3288
3289 \return - None
3290
3291 --------------------------------------------------------------------------*/
3292static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
3293{
3294 struct fullPowerContext *pContext = callbackContext;
3295
3296 hddLog(VOS_TRACE_LEVEL_INFO,
3297 "%s: context = %p, status = %d", pContext, status);
3298
3299 if (NULL == callbackContext)
3300 {
3301 hddLog(VOS_TRACE_LEVEL_ERROR,
3302 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003303 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07003304 return;
3305 }
3306
3307 /* there is a race condition that exists between this callback function
3308 and the caller since the caller could time out either before or
3309 while this code is executing. we'll assume the timeout hasn't
3310 occurred, but we'll verify that right before we save our work */
3311
3312 if (POWER_CONTEXT_MAGIC != pContext->magic)
3313 {
3314 /* the caller presumably timed out so there is nothing we can do */
3315 hddLog(VOS_TRACE_LEVEL_WARN,
3316 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003317 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07003318 return;
3319 }
3320
3321 /* the race is on. caller could have timed out immediately after
3322 we verified the magic, but if so, caller will wait a short time
3323 for us to notify the caller, so the context will stay valid */
3324 complete(&pContext->completion);
3325}
3326
3327/**---------------------------------------------------------------------------
3328
3329 \brief hdd_wlan_exit() - HDD WLAN exit function
3330
3331 This is the driver exit point (invoked during rmmod)
3332
3333 \param - pHddCtx - Pointer to the HDD Context
3334
3335 \return - None
3336
3337 --------------------------------------------------------------------------*/
3338void hdd_wlan_exit(hdd_context_t *pHddCtx)
3339{
3340 eHalStatus halStatus;
3341 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
3342 VOS_STATUS vosStatus;
3343#ifdef ANI_BUS_TYPE_SDIO
3344 struct sdio_func *sdio_func_dev = NULL;
3345#endif // ANI_BUS_TYPE_SDIO
3346#ifdef CONFIG_CFG80211
3347 struct wiphy *wiphy = pHddCtx->wiphy;
3348#endif
3349#ifdef FEATURE_WLAN_INTEGRATED_SOC
3350 hdd_adapter_t* pAdapter;
3351#endif
3352 struct fullPowerContext powerContext;
3353 long lrc;
3354
3355 ENTER();
3356
Ng Chilam1322ea32012-12-27 17:33:08 -08003357#ifdef ANI_MANF_DIAG
3358 if (VOS_FTM_MODE != hdd_get_conparam())
3359#endif /* ANI_MANF_DIAG */
3360 {
3361 // Unloading, restart logic is no more required.
3362 wlan_hdd_restart_deinit(pHddCtx);
3363 }
Jeff Johnsone7245742012-09-05 17:12:55 -07003364
Jeff Johnson295189b2012-06-20 16:38:30 -07003365#ifdef CONFIG_CFG80211
3366#ifdef WLAN_SOFTAP_FEATURE
3367 if (VOS_STA_SAP_MODE != hdd_get_conparam())
3368#endif
3369 {
3370#ifdef ANI_MANF_DIAG
3371 if (VOS_FTM_MODE != hdd_get_conparam())
3372#endif /* ANI_MANF_DIAG */
3373 {
3374 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
3375 WLAN_HDD_INFRA_STATION);
3376 if (pAdapter == NULL)
3377 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
3378
3379 if (pAdapter != NULL)
3380 {
3381 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
3382 hdd_UnregisterWext(pAdapter->dev);
3383 }
3384 }
3385 }
3386#endif
3387
3388#ifdef ANI_MANF_DIAG
3389 if (VOS_FTM_MODE == hdd_get_conparam())
3390 {
3391 wlan_hdd_ftm_close(pHddCtx);
3392 goto free_hdd_ctx;
3393 }
3394#endif
3395 //Stop the Interface TX queue.
3396 //netif_tx_disable(pWlanDev);
3397 //netif_carrier_off(pWlanDev);
3398
Jeff Johnson295189b2012-06-20 16:38:30 -07003399#ifdef FEATURE_WLAN_INTEGRATED_SOC
3400#ifdef WLAN_SOFTAP_FEATURE
3401 if (VOS_STA_SAP_MODE == hdd_get_conparam())
3402 {
3403 pAdapter = hdd_get_adapter(pHddCtx,
3404 WLAN_HDD_SOFTAP);
3405 }
3406 else
3407 {
3408#endif
3409#ifdef ANI_MANF_DIAG
3410 if (VOS_FTM_MODE != hdd_get_conparam())
3411#endif /* ANI_MANF_DIAG */
3412 {
3413 pAdapter = hdd_get_adapter(pHddCtx,
3414 WLAN_HDD_INFRA_STATION);
3415 }
3416#ifdef WLAN_SOFTAP_FEATURE
3417 }
3418#endif
3419 /* DeRegister with platform driver as client for Suspend/Resume */
3420 vosStatus = hddDeregisterPmOps(pHddCtx);
3421 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3422 {
3423 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
3424 VOS_ASSERT(0);
3425 }
3426
3427 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
3428 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
3429 {
3430 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
3431 }
3432#endif //FEATURE_WLAN_INTEGRATED_SOC
3433
Chilam NG571c65a2013-01-19 12:27:36 +05303434#ifdef FEATURE_WLAN_TDLS
3435 wlan_hdd_tdls_exit();
3436#endif
3437
Jeff Johnson295189b2012-06-20 16:38:30 -07003438 // Cancel any outstanding scan requests. We are about to close all
3439 // of our adapters, but an adapter structure is what SME passes back
3440 // to our callback function. Hence if there are any outstanding scan
3441 // requests then there is a race condition between when the adapter
3442 // is closed and when the callback is invoked. We try to resolve that
3443 // race condition here by canceling any outstanding scans before we
3444 // close the adapters.
3445 // Note that the scans may be cancelled in an asynchronous manner, so
3446 // ideally there needs to be some kind of synchronization. Rather than
3447 // introduce a new synchronization here, we will utilize the fact that
3448 // we are about to Request Full Power, and since that is synchronized,
3449 // the expectation is that by the time Request Full Power has completed,
3450 // all scans will be cancelled.
3451 hdd_abort_mac_scan( pHddCtx );
3452
3453 //Disable IMPS/BMPS as we do not want the device to enter any power
3454 //save mode during shutdown
3455 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
3456 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
3457 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
3458
3459 //Ensure that device is in full power as we will touch H/W during vos_Stop
3460 init_completion(&powerContext.completion);
3461 powerContext.magic = POWER_CONTEXT_MAGIC;
3462
3463 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
3464 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
3465
3466 if (eHAL_STATUS_SUCCESS != halStatus)
3467 {
3468 if (eHAL_STATUS_PMC_PENDING == halStatus)
3469 {
3470 /* request was sent -- wait for the response */
3471 lrc = wait_for_completion_interruptible_timeout(
3472 &powerContext.completion,
3473 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
3474 /* either we have a response or we timed out
3475 either way, first invalidate our magic */
3476 powerContext.magic = 0;
3477 if (lrc <= 0)
3478 {
3479 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003480 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07003481 /* there is a race condition such that the callback
3482 function could be executing at the same time we are. of
3483 primary concern is if the callback function had already
3484 verified the "magic" but hasn't yet set the completion
3485 variable. Since the completion variable is on our
3486 stack, we'll delay just a bit to make sure the data is
3487 still valid if that is the case */
3488 msleep(50);
3489 }
3490 }
3491 else
3492 {
3493 hddLog(VOS_TRACE_LEVEL_ERROR,
3494 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003495 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07003496 VOS_ASSERT(0);
3497 /* continue -- need to clean up as much as possible */
3498 }
3499 }
3500
3501 // Unregister the Net Device Notifier
3502 unregister_netdevice_notifier(&hdd_netdev_notifier);
3503
Jeff Johnson295189b2012-06-20 16:38:30 -07003504 hdd_stop_all_adapters( pHddCtx );
3505
3506#ifdef ANI_BUS_TYPE_SDIO
3507 sdio_func_dev = libra_getsdio_funcdev();
3508
3509 if(sdio_func_dev == NULL)
3510 {
3511 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: sdio_func_dev is NULL!",__func__);
3512 VOS_ASSERT(0);
3513 return;
3514 }
3515
3516 sd_claim_host(sdio_func_dev);
3517
3518 /* Disable SDIO IRQ since we are exiting */
3519 libra_enable_sdio_irq(sdio_func_dev, 0);
3520
3521 sd_release_host(sdio_func_dev);
3522#endif // ANI_BUS_TYPE_SDIO
3523
3524#ifdef WLAN_BTAMP_FEATURE
3525 vosStatus = WLANBAP_Stop(pVosContext);
3526 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3527 {
3528 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
3529 "%s: Failed to stop BAP",__func__);
3530 }
3531#endif //WLAN_BTAMP_FEATURE
3532
3533 //Stop all the modules
3534 vosStatus = vos_stop( pVosContext );
3535 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3536 {
3537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3538 "%s: Failed to stop VOSS",__func__);
3539 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3540 }
3541
3542#ifdef ANI_BUS_TYPE_SDIO
3543 vosStatus = WLANBAL_Stop( pVosContext );
3544
3545 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN BAL STOP\n");
3546 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3547 {
3548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3549 "%s: Failed to stop BAL",__func__);
3550 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3551 }
3552
3553 msleep(50);
3554 //Put the chip is standby before asserting deep sleep
3555 vosStatus = WLANBAL_SuspendChip( pVosContext );
3556
3557 hddLog(VOS_TRACE_LEVEL_ERROR,"WLAN Suspend Chip\n");
3558
3559 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3560 {
3561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3562 "%s: Failed to suspend chip ",__func__);
3563 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3564 }
3565 //Invoke SAL stop
3566 vosStatus = WLANSAL_Stop( pVosContext );
3567 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3568 {
3569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3570 "%s: Failed to stop SAL",__func__);
3571 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3572 }
3573
3574#endif // ANI_BUS_TYPE_SDIO
3575
3576 //Assert Deep sleep signal now to put Libra HW in lowest power state
3577 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
3578 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3579
3580 //Vote off any PMIC voltage supplies
3581 vos_chipPowerDown(NULL, NULL, NULL);
3582
3583 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
3584
3585 //Clean up HDD Nlink Service
3586 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
3587 nl_srv_exit();
3588
3589 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07003590 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07003591
3592 //Close the scheduler before calling vos_close to make sure no thread is
3593 // scheduled after the each module close is called i.e after all the data
3594 // structures are freed.
3595 vosStatus = vos_sched_close( pVosContext );
3596 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
3597 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
3598 "%s: Failed to close VOSS Scheduler",__func__);
3599 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3600 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003601#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07003602#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
3603 /* Destroy the wake lock */
3604 wake_lock_destroy(&pHddCtx->rx_wake_lock);
3605#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08003606 /* Destroy the wake lock */
3607 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003608#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003609
3610 //Close VOSS
3611 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
3612 vos_close(pVosContext);
3613
3614#ifdef ANI_BUS_TYPE_SDIO
3615 vosStatus = WLANBAL_Close(pVosContext);
3616 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
3617 {
3618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
3619 "%s: Failed to close BAL",__func__);
3620 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
3621 }
3622 hddLog(VOS_TRACE_LEVEL_ERROR,"Returned WLAN BAL CLOSE\n\n\n\n");
3623#endif // ANI_BUS_TYPE_SDIO
3624
3625 //Close Watchdog
3626 if(pHddCtx->cfg_ini->fIsLogpEnabled)
3627 vos_watchdog_close(pVosContext);
3628
3629 /* Cancel the vote for XO Core ON.
3630 * This is done here to ensure there is no race condition since MC, TX and WD threads have
3631 * exited at this point
3632 */
3633 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
3634 " when WLAN is turned OFF\n");
3635 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
3636 {
3637 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
3638 " Not returning failure."
3639 " Power consumed will be high\n");
3640 }
3641
3642 hdd_close_all_adapters( pHddCtx );
3643
3644
3645 //Free up dynamically allocated members inside HDD Adapter
3646 kfree(pHddCtx->cfg_ini);
3647 pHddCtx->cfg_ini= NULL;
3648
3649 /* free the power on lock from platform driver */
3650 if (free_riva_power_on_lock("wlan"))
3651 {
3652 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
3653 __func__);
3654 }
3655
3656#ifdef ANI_MANF_DIAG
3657free_hdd_ctx:
3658#endif
3659#ifdef CONFIG_CFG80211
3660 wiphy_unregister(wiphy) ;
3661 wiphy_free(wiphy) ;
3662#else
3663 vos_mem_free( pHddCtx );
3664#endif
3665 if (hdd_is_ssr_required())
3666 {
3667 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07003668 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07003669 msleep(5000);
3670 }
3671 hdd_set_ssr_required (VOS_FALSE);
3672}
3673
3674
3675/**---------------------------------------------------------------------------
3676
3677 \brief hdd_update_config_from_nv() - Function to update the contents of
3678 the running configuration with parameters taken from NV storage
3679
3680 \param - pHddCtx - Pointer to the HDD global context
3681
3682 \return - VOS_STATUS_SUCCESS if successful
3683
3684 --------------------------------------------------------------------------*/
3685static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
3686{
3687#ifndef FEATURE_WLAN_INTEGRATED_SOC
3688 eHalStatus halStatus;
3689#endif
3690
3691#ifdef FEATURE_WLAN_INTEGRATED_SOC
3692 v_BOOL_t itemIsValid = VOS_FALSE;
3693 VOS_STATUS status;
3694 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
3695 v_U8_t macLoop;
3696
3697 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
3698 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
3699 if(status != VOS_STATUS_SUCCESS)
3700 {
3701 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
3702 return VOS_STATUS_E_FAILURE;
3703 }
3704
3705 if (itemIsValid == VOS_TRUE)
3706 {
3707 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
3708 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
3709 VOS_MAX_CONCURRENCY_PERSONA);
3710 if(status != VOS_STATUS_SUCCESS)
3711 {
3712 /* Get MAC from NV fail, not update CFG info
3713 * INI MAC value will be used for MAC setting */
3714 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
3715 return VOS_STATUS_E_FAILURE;
3716 }
3717
3718 /* If first MAC is not valid, treat all others are not valid
3719 * Then all MACs will be got from ini file */
3720 if(vos_is_macaddr_zero(&macFromNV[0]))
3721 {
3722 /* MAC address in NV file is not configured yet */
3723 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
3724 return VOS_STATUS_E_INVAL;
3725 }
3726
3727 /* Get MAC address from NV, update CFG info */
3728 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
3729 {
3730 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
3731 {
3732 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
3733 /* This MAC is not valid, skip it
3734 * This MAC will be got from ini file */
3735 }
3736 else
3737 {
3738 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
3739 (v_U8_t *)&macFromNV[macLoop].bytes[0],
3740 VOS_MAC_ADDR_SIZE);
3741 }
3742 }
3743 }
3744 else
3745 {
3746 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
3747 return VOS_STATUS_E_FAILURE;
3748 }
3749#endif /* FEATURE_WLAN_INTEGRATED_SOC */
3750
3751#ifndef FEATURE_WLAN_INTEGRATED_SOC
3752#if 1 /* need to fix for concurrency */
3753 // Set the MAC Address
3754 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
3755 halStatus = ccmCfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
3756 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
3757 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]),
3758 hdd_set_mac_addr_cb, VOS_FALSE );
3759
3760 if (!HAL_STATUS_SUCCESS( halStatus ))
3761 {
3762 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
3763 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
3764 return VOS_STATUS_E_FAILURE;
3765 }
3766#endif
3767#endif
3768
3769 return VOS_STATUS_SUCCESS;
3770}
3771
3772/**---------------------------------------------------------------------------
3773
3774 \brief hdd_post_voss_start_config() - HDD post voss start config helper
3775
3776 \param - pAdapter - Pointer to the HDD
3777
3778 \return - None
3779
3780 --------------------------------------------------------------------------*/
3781VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
3782{
3783 eHalStatus halStatus;
3784 v_U32_t listenInterval;
3785
3786#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
3787 /* In the non-integrated architecture we update the configuration from
3788 the INI file and from NV after vOSS has been started
3789 */
3790
3791 // Apply the cfg.ini to cfg.dat
3792 if (FALSE == hdd_update_config_dat(pHddCtx))
3793 {
3794 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
3795 return VOS_STATUS_E_FAILURE;
3796 }
3797
3798 // Apply the NV to cfg.dat
3799 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
3800 {
3801 hddLog(VOS_TRACE_LEVEL_FATAL,
3802 "%s: config update from NV failed", __func__ );
3803 return VOS_STATUS_E_FAILURE;
3804 }
3805#endif // FEATURE_WLAN_NON_INTEGRATED_SOC
3806
3807 // Send ready indication to the HDD. This will kick off the MAC
3808 // into a 'running' state and should kick off an initial scan.
3809 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
3810 if ( !HAL_STATUS_SUCCESS( halStatus ) )
3811 {
3812 hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status "
3813 "code %08d [x%08x]",__func__, halStatus, halStatus );
3814 return VOS_STATUS_E_FAILURE;
3815 }
3816
3817 // Set default LI into HDD context,
3818 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
3819 // And RIVA will crash
3820 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
3821 pHddCtx->hdd_actual_LI_value = listenInterval;
3822
3823 return VOS_STATUS_SUCCESS;
3824}
3825
3826#ifdef ANI_BUS_TYPE_SDIO
3827
3828#ifndef ANI_MANF_DIAG
3829// Routine to initialize the PMU
3830void wlan_hdd_enable_deepsleep(v_VOID_t * pVosContext)
3831{
3832/*-------------- Need to fix this correctly while doing Deepsleep testing
3833 tANI_U32 regValue = 0;
3834
3835 regValue = QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_DEEP_SLEEP_EN_MASK |
3836 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_AON_MASK_MASK |
3837 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_1P23_LPM_SW_MASK_MASK |
3838 QWLAN_PMU_LDO_CTRL_REG_PMU_ANA_2P3_LPM_MASK_MASK;
3839
3840 WLANBAL_WriteRegister(pVosContext, QWLAN_PMU_LDO_CTRL_REG_REG, regValue);
3841---------------------*/
3842
3843 return;
3844}
3845#endif
3846#endif
3847
3848/* wake lock APIs for HDD */
3849void hdd_prevent_suspend(void)
3850{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003851#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003852 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003853#else
3854 wcnss_prevent_suspend();
3855#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003856}
3857
3858void hdd_allow_suspend(void)
3859{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003860#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07003861 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07003862#else
3863 wcnss_allow_suspend();
3864#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07003865}
3866
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003867void hdd_allow_suspend_timeout(v_U32_t timeout)
3868{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08003869#ifdef WLAN_OPEN_SOURCE
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07003870 wake_lock_timeout(&wlan_wake_lock, timeout);
3871#else
3872 /* Do nothing as there is no API in wcnss for timeout*/
3873#endif
3874}
3875
Jeff Johnson295189b2012-06-20 16:38:30 -07003876/**---------------------------------------------------------------------------
3877
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003878 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
3879 information between Host and Riva
3880
3881 This function gets reported version of FW
3882 It also finds the version of Riva headers used to compile the host
3883 It compares the above two and prints a warning if they are different
3884 It gets the SW and HW version string
3885 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
3886 indicating the features they support through a bitmap
3887
3888 \param - pHddCtx - Pointer to HDD context
3889
3890 \return - void
3891
3892 --------------------------------------------------------------------------*/
3893
3894void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
3895{
3896
3897 tSirVersionType versionCompiled;
3898 tSirVersionType versionReported;
3899 tSirVersionString versionString;
3900 tANI_U8 fwFeatCapsMsgSupported = 0;
3901 VOS_STATUS vstatus;
3902
3903 /* retrieve and display WCNSS version information */
3904 do {
3905
3906 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
3907 &versionCompiled);
3908 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3909 {
3910 hddLog(VOS_TRACE_LEVEL_FATAL,
3911 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003912 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003913 break;
3914 }
3915
3916 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
3917 &versionReported);
3918 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3919 {
3920 hddLog(VOS_TRACE_LEVEL_FATAL,
3921 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003922 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003923 break;
3924 }
3925
3926 if ((versionCompiled.major != versionReported.major) ||
3927 (versionCompiled.minor != versionReported.minor) ||
3928 (versionCompiled.version != versionReported.version) ||
3929 (versionCompiled.revision != versionReported.revision))
3930 {
3931 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
3932 "Host expected %u.%u.%u.%u\n",
3933 WLAN_MODULE_NAME,
3934 (int)versionReported.major,
3935 (int)versionReported.minor,
3936 (int)versionReported.version,
3937 (int)versionReported.revision,
3938 (int)versionCompiled.major,
3939 (int)versionCompiled.minor,
3940 (int)versionCompiled.version,
3941 (int)versionCompiled.revision);
3942 }
3943 else
3944 {
3945 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
3946 WLAN_MODULE_NAME,
3947 (int)versionReported.major,
3948 (int)versionReported.minor,
3949 (int)versionReported.version,
3950 (int)versionReported.revision);
3951 }
3952
3953 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
3954 versionString,
3955 sizeof(versionString));
3956 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3957 {
3958 hddLog(VOS_TRACE_LEVEL_FATAL,
3959 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003960 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003961 break;
3962 }
3963
3964 pr_info("%s: WCNSS software version %s\n",
3965 WLAN_MODULE_NAME, versionString);
3966
3967 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
3968 versionString,
3969 sizeof(versionString));
3970 if (!VOS_IS_STATUS_SUCCESS(vstatus))
3971 {
3972 hddLog(VOS_TRACE_LEVEL_FATAL,
3973 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003974 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003975 break;
3976 }
3977
3978 pr_info("%s: WCNSS hardware version %s\n",
3979 WLAN_MODULE_NAME, versionString);
3980
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003981 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
3982 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003983 send the message only if it the riva is 1.1
3984 minor numbers for different riva branches:
3985 0 -> (1.0)Mainline Build
3986 1 -> (1.1)Mainline Build
3987 2->(1.04) Stability Build
3988 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003989 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003990 ((versionReported.minor>=1) && (versionReported.version>=1)))
3991 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
3992 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07003993
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07003994 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08003995 {
3996#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
3997 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
3998 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
3999#endif
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004000 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08004001 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004002
4003 } while (0);
4004
4005}
4006
4007/**---------------------------------------------------------------------------
4008
Jeff Johnson295189b2012-06-20 16:38:30 -07004009 \brief hdd_wlan_startup() - HDD init function
4010
4011 This is the driver startup code executed once a WLAN device has been detected
4012
4013 \param - dev - Pointer to the underlying device
4014
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004015 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07004016
4017 --------------------------------------------------------------------------*/
4018
4019int hdd_wlan_startup(struct device *dev )
4020{
4021 VOS_STATUS status;
4022 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07004023 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004024 hdd_context_t *pHddCtx = NULL;
4025 v_CONTEXT_t pVosContext= NULL;
4026#ifdef WLAN_BTAMP_FEATURE
4027 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
4028 WLANBAP_ConfigType btAmpConfig;
4029 hdd_config_t *pConfig;
4030#endif
4031 int ret;
4032#ifdef CONFIG_CFG80211
4033 struct wiphy *wiphy;
4034#endif
4035#ifdef ANI_BUS_TYPE_SDIO
4036 struct sdio_func *sdio_func_dev = dev_to_sdio_func(dev);
4037#endif //ANI_BUS_TYPE_SDIO
4038
4039 ENTER();
4040#ifdef CONFIG_CFG80211
4041 /*
4042 * cfg80211: wiphy allocation
4043 */
4044 wiphy = wlan_hdd_cfg80211_init(sizeof(hdd_context_t)) ;
4045
4046 if(wiphy == NULL)
4047 {
4048 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004049 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004050 }
4051
4052 pHddCtx = wiphy_priv(wiphy);
4053
4054#else
4055
4056 pHddCtx = vos_mem_malloc ( sizeof( hdd_context_t ) );
4057 if(pHddCtx == NULL)
4058 {
4059 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004060 return -ENOMEM;
Jeff Johnson295189b2012-06-20 16:38:30 -07004061 }
4062
4063#endif
4064 //Initialize the adapter context to zeros.
4065 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
4066
4067#ifdef CONFIG_CFG80211
4068 pHddCtx->wiphy = wiphy;
4069#endif
4070 hdd_prevent_suspend();
4071 pHddCtx->isLoadUnloadInProgress = TRUE;
4072
4073 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
4074
4075 /*Get vos context here bcoz vos_open requires it*/
4076 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4077
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08004078 if(pVosContext == NULL)
4079 {
4080 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
4081 goto err_free_hdd_context;
4082 }
4083
Jeff Johnson295189b2012-06-20 16:38:30 -07004084 //Save the Global VOSS context in adapter context for future.
4085 pHddCtx->pvosContext = pVosContext;
4086
4087 //Save the adapter context in global context for future.
4088 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
4089
4090#ifdef ANI_BUS_TYPE_SDIO
4091 // Set the private data for the device to our adapter.
4092 libra_sdio_setprivdata (sdio_func_dev, pHddCtx);
4093 atomic_set(&pHddCtx->sdio_claim_count, 0);
4094#endif // ANI_BUS_TYPE_SDIO
4095
4096 pHddCtx->parent_dev = dev;
4097
4098 init_completion(&pHddCtx->full_pwr_comp_var);
4099 init_completion(&pHddCtx->standby_comp_var);
4100 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004101 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08004102 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -07004103
4104 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
4105
4106 // Load all config first as TL config is needed during vos_open
4107 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
4108 if(pHddCtx->cfg_ini == NULL)
4109 {
4110 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
4111 goto err_free_hdd_context;
4112 }
4113
4114 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
4115
4116 // Read and parse the qcom_cfg.ini file
4117 status = hdd_parse_config_ini( pHddCtx );
4118 if ( VOS_STATUS_SUCCESS != status )
4119 {
4120 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
4121 __func__, WLAN_INI_FILE);
4122 goto err_config;
4123 }
4124
4125#ifdef CONFIG_CFG80211
4126 /*
4127 * cfg80211: Initialization and registration ...
4128 */
4129 if (0 < wlan_hdd_cfg80211_register(dev, wiphy, pHddCtx->cfg_ini))
4130 {
4131 hddLog(VOS_TRACE_LEVEL_FATAL,
4132 "%s: wlan_hdd_cfg80211_register return failure", __func__);
4133 goto err_wiphy_reg;
4134 }
4135#endif
4136
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08004137 // Update VOS trace levels based upon the cfg.ini
4138 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
4139 pHddCtx->cfg_ini->vosTraceEnableBAP);
4140 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
4141 pHddCtx->cfg_ini->vosTraceEnableTL);
4142 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
4143 pHddCtx->cfg_ini->vosTraceEnableWDI);
4144 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
4145 pHddCtx->cfg_ini->vosTraceEnableHDD);
4146 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
4147 pHddCtx->cfg_ini->vosTraceEnableSME);
4148 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
4149 pHddCtx->cfg_ini->vosTraceEnablePE);
4150 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
4151 pHddCtx->cfg_ini->vosTraceEnableWDA);
4152 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
4153 pHddCtx->cfg_ini->vosTraceEnableSYS);
4154 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
4155 pHddCtx->cfg_ini->vosTraceEnableVOSS);
4156#ifdef WLAN_SOFTAP_FEATURE
4157 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
4158 pHddCtx->cfg_ini->vosTraceEnableSAP);
4159 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
4160 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
4161#endif
4162
Jeff Johnson295189b2012-06-20 16:38:30 -07004163#ifdef FEATURE_WLAN_INTEGRATED_SOC
4164 // Update WDI trace levels based upon the cfg.ini
4165 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
4166 pHddCtx->cfg_ini->wdiTraceEnableDAL);
4167 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
4168 pHddCtx->cfg_ini->wdiTraceEnableCTL);
4169 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
4170 pHddCtx->cfg_ini->wdiTraceEnableDAT);
4171 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
4172 pHddCtx->cfg_ini->wdiTraceEnablePAL);
4173#endif /* FEATURE_WLAN_INTEGRATED_SOC */
4174
4175#ifdef ANI_MANF_DIAG
4176 if(VOS_FTM_MODE == hdd_get_conparam())
4177 {
4178 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
4179 {
4180 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
4181 goto err_free_hdd_context;
4182 }
4183 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
4184 return VOS_STATUS_SUCCESS;
4185 }
4186#endif
4187
4188 //Open watchdog module
4189 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4190 {
4191 status = vos_watchdog_open(pVosContext,
4192 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
4193
4194 if(!VOS_IS_STATUS_SUCCESS( status ))
4195 {
4196 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
4197#ifdef CONFIG_CFG80211
4198 goto err_wiphy_reg;
4199#else
4200 goto err_config;
4201#endif
4202 }
4203 }
4204
4205 pHddCtx->isLogpInProgress = FALSE;
4206 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4207
4208#ifdef ANI_BUS_TYPE_SDIO
4209 status = WLANBAL_Open(pHddCtx->pvosContext);
4210 if(!VOS_IS_STATUS_SUCCESS(status))
4211 {
4212 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4213 "%s: Failed to open BAL",__func__);
4214 goto err_wdclose;
4215 }
4216#endif // ANI_BUS_TYPE_SDIO
4217
4218 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
4219 if(!VOS_IS_STATUS_SUCCESS(status))
4220 {
4221 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
4222#ifdef ANI_BUS_TYPE_SDIO
4223 goto err_balclose;
4224#else
4225 goto err_wdclose;
4226#endif
4227 }
4228
4229
4230#ifdef ANI_BUS_TYPE_SDIO
4231 status = WLANSAL_Start(pHddCtx->pvosContext);
4232 if (!VOS_IS_STATUS_SUCCESS(status))
4233 {
4234 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to start SAL",__func__);
4235 goto err_clkvote;
4236 }
4237
4238 /* Start BAL */
4239 status = WLANBAL_Start(pHddCtx->pvosContext);
4240
4241 if (!VOS_IS_STATUS_SUCCESS(status))
4242 {
4243 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4244 "%s: Failed to start BAL",__func__);
4245 goto err_salstop;
4246 }
4247#endif // ANI_BUS_TYPE_SDIO
4248
4249#ifdef MSM_PLATFORM_7x30
4250 /* FIXME: Volans 2.0 configuration. Reconfigure 1.3v SW supply to 1.3v. It will be configured to
4251 * 1.4v in vos_ChipPowerup() routine above
4252 */
4253#endif
4254
4255 status = vos_open( &pVosContext, 0);
4256 if ( !VOS_IS_STATUS_SUCCESS( status ))
4257 {
4258 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__);
4259 goto err_balstop;
4260 }
4261
4262 /* Save the hal context in Adapter */
4263 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
4264
4265 if ( NULL == pHddCtx->hHal )
4266 {
4267 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HAL context is null",__func__);
4268 goto err_vosclose;
4269 }
4270
Jeff Johnsone7245742012-09-05 17:12:55 -07004271#ifdef FEATURE_WLAN_INTEGRATED_SOC
4272 /* Vos preStart is calling */
4273 /* vos preStart which does cfg download should be called before set sme config which accesses/sets some cfgs */
4274 status = vos_preStart( pHddCtx->pvosContext );
4275 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4276 {
4277 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_preStart failed",__func__);
4278 goto err_vosclose;
4279 }
4280#endif
4281
Jeff Johnson295189b2012-06-20 16:38:30 -07004282 // Set the SME configuration parameters...
4283 status = hdd_set_sme_config( pHddCtx );
4284
4285 if ( VOS_STATUS_SUCCESS != status )
4286 {
4287 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed hdd_set_sme_config",__func__);
4288 goto err_vosclose;
4289 }
4290
4291 //Initialize the WMM module
4292 status = hdd_wmm_init(pHddCtx);
4293 if (!VOS_IS_STATUS_SUCCESS(status))
4294 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004295 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004296 goto err_vosclose;
4297 }
4298
4299#ifdef FEATURE_WLAN_INTEGRATED_SOC
Jeff Johnson295189b2012-06-20 16:38:30 -07004300 /* In the integrated architecture we update the configuration from
4301 the INI file and from NV before vOSS has been started so that
4302 the final contents are available to send down to the cCPU */
4303
4304 // Apply the cfg.ini to cfg.dat
4305 if (FALSE == hdd_update_config_dat(pHddCtx))
4306 {
4307 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
4308 goto err_vosclose;
4309 }
4310
4311 // Apply the NV to cfg.dat
4312 /* Prima Update MAC address only at here */
4313 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
4314 {
4315#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
4316 /* There was not a valid set of MAC Addresses in NV. See if the
4317 default addresses were modified by the cfg.ini settings. If so,
4318 we'll use them, but if not, we'll autogenerate a set of MAC
4319 addresses based upon the device serial number */
4320
4321 static const v_MACADDR_t default_address =
4322 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
4323 unsigned int serialno;
4324 int i;
4325
4326 serialno = wcnss_get_serial_number();
4327 if ((0 != serialno) &&
4328 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
4329 sizeof(default_address))))
4330 {
4331 /* cfg.ini has the default address, invoke autogen logic */
4332
4333 /* MAC address has 3 bytes of OUI so we have a maximum of 3
4334 bytes of the serial number that can be used to generate
4335 the other 3 bytes of the MAC address. Mask off all but
4336 the lower 3 bytes (this will also make sure we don't
4337 overflow in the next step) */
4338 serialno &= 0x00FFFFFF;
4339
4340 /* we need a unique address for each session */
4341 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
4342
4343 /* autogen all addresses */
4344 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4345 {
4346 /* start with the entire default address */
4347 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
4348 /* then replace the lower 3 bytes */
4349 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
4350 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
4351 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
4352
4353 serialno++;
4354 }
4355
4356 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
4357 MAC_ADDRESS_STR,
4358 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4359 }
4360 else
4361#endif //WLAN_AUTOGEN_MACADDR_FEATURE
4362 {
4363 hddLog(VOS_TRACE_LEVEL_ERROR,
4364 "%s: Invalid MAC address in NV, using MAC from ini file "
4365 MAC_ADDRESS_STR, __func__,
4366 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
4367 }
4368 }
4369 {
4370 eHalStatus halStatus;
4371 // Set the MAC Address
4372 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
4373 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
4374 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
4375 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
4376
4377 if (!HAL_STATUS_SUCCESS( halStatus ))
4378 {
4379 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
4380 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08004381 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07004382 }
4383 }
4384#endif // FEATURE_WLAN_INTEGRATED_SOC
4385
4386 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
4387 Note: Firmware image will be read and downloaded inside vos_start API */
4388 status = vos_start( pHddCtx->pvosContext );
4389 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4390 {
4391 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
4392 goto err_vosclose;
4393 }
4394
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07004395 /* Exchange capability info between Host and FW and also get versioning info from FW */
4396 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004397
4398 status = hdd_post_voss_start_config( pHddCtx );
4399 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4400 {
4401 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
4402 __func__);
4403 goto err_vosstop;
4404 }
4405
4406#ifdef WLAN_SOFTAP_FEATURE
4407 if (VOS_STA_SAP_MODE == hdd_get_conparam())
4408 {
4409 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
4410 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4411 }
4412 else
4413 {
4414#endif
4415 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
4416 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
4417 if (pAdapter != NULL)
4418 {
4419#ifdef WLAN_FEATURE_P2P
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304420 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07004421 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304422 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
4423 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
4424 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07004425
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304426 /* Generate the P2P Device Address. This consists of the device's
4427 * primary MAC address with the locally administered bit set.
4428 */
4429 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07004430 }
4431 else
4432 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05304433 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
4434 if (p2p_dev_addr != NULL)
4435 {
4436 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
4437 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
4438 }
4439 else
4440 {
4441 hddLog(VOS_TRACE_LEVEL_FATAL,
4442 "%s: Failed to allocate mac_address for p2p_device",
4443 __func__);
4444 goto err_close_adapter;
4445 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004446 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004447
4448 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
4449 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
4450 if ( NULL == pP2pAdapter )
4451 {
4452 hddLog(VOS_TRACE_LEVEL_FATAL,
4453 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004454 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004455 goto err_close_adapter;
4456 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004457#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004458 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004459#ifdef WLAN_SOFTAP_FEATURE
4460 }
4461#endif
4462
4463 if( pAdapter == NULL )
4464 {
4465 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__);
4466#ifdef ANI_BUS_TYPE_SDIO
4467 goto err_balstop;
4468#else
Jeff Johnson546a5c12013-02-15 10:11:20 -08004469 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004470#endif
4471 }
Jeff Johnsone7245742012-09-05 17:12:55 -07004472
Jeff Johnson295189b2012-06-20 16:38:30 -07004473#ifdef WLAN_BTAMP_FEATURE
4474 vStatus = WLANBAP_Open(pVosContext);
4475 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4476 {
4477 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4478 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07004479 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004480 }
4481
4482 vStatus = BSL_Init(pVosContext);
4483 if(!VOS_IS_STATUS_SUCCESS(vStatus))
4484 {
4485 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4486 "%s: Failed to Init BSL",__func__);
4487 goto err_bap_close;
4488 }
4489 vStatus = WLANBAP_Start(pVosContext);
4490 if (!VOS_IS_STATUS_SUCCESS(vStatus))
4491 {
4492 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
4493 "%s: Failed to start TL",__func__);
4494 goto err_bap_close;
4495 }
4496
4497 pConfig = pHddCtx->cfg_ini;
4498 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
4499 status = WLANBAP_SetConfig(&btAmpConfig);
4500
4501#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07004502
Jeff Johnson295189b2012-06-20 16:38:30 -07004503#ifdef FEATURE_WLAN_SCAN_PNO
4504 /*SME must send channel update configuration to RIVA*/
4505 sme_UpdateChannelConfig(pHddCtx->hHal);
4506#endif
4507
4508#ifdef FEATURE_WLAN_INTEGRATED_SOC
4509 /* Register with platform driver as client for Suspend/Resume */
4510 status = hddRegisterPmOps(pHddCtx);
4511 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4512 {
4513 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
4514#ifdef WLAN_BTAMP_FEATURE
4515 goto err_bap_stop;
4516#else
Jeff Johnsone7245742012-09-05 17:12:55 -07004517 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07004518#endif //WLAN_BTAMP_FEATURE
4519 }
4520
4521 /* Register TM level change handler function to the platform */
4522 status = hddDevTmRegisterNotifyCallback(pHddCtx);
4523 if ( !VOS_IS_STATUS_SUCCESS( status ) )
4524 {
4525 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
4526 goto err_unregister_pmops;
4527 }
4528#endif
4529
4530 /* register for riva power on lock to platform driver */
4531 if (req_riva_power_on_lock("wlan"))
4532 {
4533 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
4534 __func__);
4535 goto err_unregister_pmops;
4536 }
4537
Jeff Johnson295189b2012-06-20 16:38:30 -07004538 // register net device notifier for device change notification
4539 ret = register_netdevice_notifier(&hdd_netdev_notifier);
4540
4541 if(ret < 0)
4542 {
4543 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
4544 goto err_free_power_on_lock;
4545 }
4546
4547 //Initialize the nlink service
4548 if(nl_srv_init() != 0)
4549 {
4550 hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__);
4551 goto err_reg_netdev;
4552 }
4553
4554 //Initialize the BTC service
4555 if(btc_activate_service(pHddCtx) != 0)
4556 {
4557 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
4558 goto err_nl_srv;
4559 }
4560
4561#ifdef PTT_SOCK_SVC_ENABLE
4562 //Initialize the PTT service
4563 if(ptt_sock_activate_svc(pHddCtx) != 0)
4564 {
4565 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
4566 goto err_nl_srv;
4567 }
4568#endif
4569
Jeff Johnson295189b2012-06-20 16:38:30 -07004570 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07004571#ifdef CONFIG_CFG80211
4572#ifdef WLAN_SOFTAP_FEATURE
4573 if (VOS_STA_SAP_MODE != hdd_get_conparam())
4574#endif
4575 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07004576 /* Action frame registered in one adapter which will
4577 * applicable to all interfaces
4578 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07004579 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004580 }
4581#endif
4582
4583 mutex_init(&pHddCtx->sap_lock);
4584
4585 pHddCtx->isLoadUnloadInProgress = FALSE;
4586
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004587#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07004588#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
4589 /* Initialize the wake lcok */
4590 wake_lock_init(&pHddCtx->rx_wake_lock,
4591 WAKE_LOCK_SUSPEND,
4592 "qcom_rx_wakelock");
4593#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08004594 /* Initialize the wake lcok */
4595 wake_lock_init(&pHddCtx->sap_wake_lock,
4596 WAKE_LOCK_SUSPEND,
4597 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004598#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07004599
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07004600 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
4601 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07004602
4603 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
4604 hdd_allow_suspend();
Jeff Johnsone7245742012-09-05 17:12:55 -07004605
4606 // Initialize the restart logic
4607 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05304608
4609#ifdef FEATURE_WLAN_TDLS
Hoonki Lee387663d2013-02-05 18:08:43 -08004610 if(0 != wlan_hdd_tdls_init(pAdapter->dev))
4611 {
4612 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_tdls_init failed",__func__);
4613 goto err_nl_srv;
4614 }
Chilam NG571c65a2013-01-19 12:27:36 +05304615#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004616
4617 goto success;
4618
4619err_nl_srv:
4620 nl_srv_exit();
4621
4622err_reg_netdev:
4623 unregister_netdevice_notifier(&hdd_netdev_notifier);
4624
4625err_free_power_on_lock:
4626 free_riva_power_on_lock("wlan");
4627
4628err_unregister_pmops:
4629 hddDevTmUnregisterNotifyCallback(pHddCtx);
4630 hddDeregisterPmOps(pHddCtx);
4631
4632#ifdef WLAN_BTAMP_FEATURE
4633err_bap_stop:
4634 WLANBAP_Stop(pVosContext);
4635#endif
4636
4637#ifdef WLAN_BTAMP_FEATURE
4638err_bap_close:
4639 WLANBAP_Close(pVosContext);
4640#endif
4641
Jeff Johnson295189b2012-06-20 16:38:30 -07004642err_close_adapter:
4643 hdd_close_all_adapters( pHddCtx );
4644
4645err_vosstop:
4646 vos_stop(pVosContext);
4647
4648err_vosclose:
4649 status = vos_sched_close( pVosContext );
4650 if (!VOS_IS_STATUS_SUCCESS(status)) {
4651 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
4652 "%s: Failed to close VOSS Scheduler", __func__);
4653 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
4654 }
4655 vos_close(pVosContext );
4656
4657err_balstop:
4658#ifdef ANI_BUS_TYPE_SDIO
4659#ifndef ANI_MANF_DIAG
4660 wlan_hdd_enable_deepsleep(pHddCtx->pvosContext);
4661#endif
4662
4663 WLANBAL_Stop(pHddCtx->pvosContext);
4664 WLANBAL_SuspendChip(pHddCtx->pvosContext);
4665#endif
4666
4667#ifdef ANI_BUS_TYPE_SDIO
4668err_salstop:
4669 WLANSAL_Stop(pHddCtx->pvosContext);
4670
Jeff Johnson295189b2012-06-20 16:38:30 -07004671err_clkvote:
Jeff Johnson546a5c12013-02-15 10:11:20 -08004672#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004673 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
4674
4675#ifdef ANI_BUS_TYPE_SDIO
4676err_balclose:
4677 WLANBAL_Close(pHddCtx->pvosContext);
4678#endif // ANI_BUS_TYPE_SDIO
4679
4680err_wdclose:
4681 if(pHddCtx->cfg_ini->fIsLogpEnabled)
4682 vos_watchdog_close(pVosContext);
4683
4684#ifdef CONFIG_CFG80211
4685err_wiphy_reg:
4686 wiphy_unregister(wiphy) ;
4687#endif
4688
4689err_config:
4690 kfree(pHddCtx->cfg_ini);
4691 pHddCtx->cfg_ini= NULL;
4692
4693err_free_hdd_context:
4694 hdd_allow_suspend();
4695#ifdef CONFIG_CFG80211
4696 wiphy_free(wiphy) ;
4697 //kfree(wdev) ;
4698#else
4699 vos_mem_free( pHddCtx );
4700#endif
4701 VOS_BUG(1);
4702
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08004703 if (hdd_is_ssr_required())
4704 {
4705 /* WDI timeout had happened during load, so SSR is needed here */
4706 subsystem_restart("wcnss");
4707 msleep(5000);
4708 }
4709 hdd_set_ssr_required (VOS_FALSE);
4710
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004711 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004712
4713success:
4714 EXIT();
4715 return 0;
4716}
4717
4718/**---------------------------------------------------------------------------
4719
Jeff Johnson32d95a32012-09-10 13:15:23 -07004720 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07004721
Jeff Johnson32d95a32012-09-10 13:15:23 -07004722 This is the driver entry point - called in different timeline depending
4723 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07004724
4725 \param - None
4726
4727 \return - 0 for success, non zero for failure
4728
4729 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07004730static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004731{
4732 VOS_STATUS status;
4733 v_CONTEXT_t pVosContext = NULL;
4734#ifdef ANI_BUS_TYPE_SDIO
4735 struct sdio_func *sdio_func_dev = NULL;
4736 unsigned int attempts = 0;
4737#endif // ANI_BUS_TYPE_SDIO
4738 struct device *dev = NULL;
4739 int ret_status = 0;
4740
4741 ENTER();
4742
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004743#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004744 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07004745#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004746
4747 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
4748 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
4749
4750 //Power Up Libra WLAN card first if not already powered up
4751 status = vos_chipPowerUp(NULL,NULL,NULL);
4752 if (!VOS_IS_STATUS_SUCCESS(status))
4753 {
4754 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
4755 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004756 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004757 }
4758
4759#ifdef ANI_BUS_TYPE_SDIO
4760 //SDIO Polling should be turned on for card detection. When using Android Wi-Fi GUI
4761 //users need not trigger SDIO polling explicitly. However when loading drivers via
4762 //command line (Adb shell), users must turn on SDIO polling prior to loading WLAN.
4763 do {
4764 sdio_func_dev = libra_getsdio_funcdev();
4765 if (NULL == sdio_func_dev) {
4766 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not detected yet.",__func__);
4767 attempts++;
4768 }
4769 else {
4770 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN detecton succeeded",__func__);
4771 dev = &sdio_func_dev->dev;
4772 break;
4773 }
4774
4775 if(attempts == 7)
4776 break;
4777
4778 msleep(250);
4779
4780 }while (attempts < 7);
4781
4782 //Retry to detect the card again by Powering Down the chip and Power up the chip
4783 //again. This retry is done to recover from CRC Error
4784 if (NULL == sdio_func_dev) {
4785
4786 attempts = 0;
4787
4788 //Vote off any PMIC voltage supplies
4789 vos_chipPowerDown(NULL, NULL, NULL);
4790
4791 msleep(1000);
4792
4793 //Power Up Libra WLAN card first if not already powered up
4794 status = vos_chipPowerUp(NULL,NULL,NULL);
4795 if (!VOS_IS_STATUS_SUCCESS(status))
4796 {
4797 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not Powered Up. "
4798 "exiting", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004799 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004800 }
4801
4802 do {
4803 sdio_func_dev = libra_getsdio_funcdev();
4804 if (NULL == sdio_func_dev) {
4805 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN not detected yet.",__func__);
4806 attempts++;
4807 }
4808 else {
4809 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Retry Libra WLAN detecton succeeded",__func__);
4810 dev = &sdio_func_dev->dev;
4811 break;
4812 }
4813
4814 if(attempts == 2)
4815 break;
4816
4817 msleep(1000);
4818
4819 }while (attempts < 3);
4820 }
4821
4822#endif // ANI_BUS_TYPE_SDIO
4823
4824#ifdef ANI_BUS_TYPE_PCI
4825
4826 dev = wcnss_wlan_get_device();
4827
4828#endif // ANI_BUS_TYPE_PCI
4829
4830#ifdef ANI_BUS_TYPE_PLATFORM
4831 dev = wcnss_wlan_get_device();
4832#endif // ANI_BUS_TYPE_PLATFORM
4833
4834
4835 do {
4836 if (NULL == dev) {
4837 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
4838 ret_status = -1;
4839 break;
4840 }
4841
4842#ifdef MEMORY_DEBUG
4843 vos_mem_init();
4844#endif
4845
4846#ifdef TIMER_MANAGER
4847 vos_timer_manager_init();
4848#endif
4849
4850 /* Preopen VOSS so that it is ready to start at least SAL */
4851 status = vos_preOpen(&pVosContext);
4852
4853 if (!VOS_IS_STATUS_SUCCESS(status))
4854 {
4855 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
4856 ret_status = -1;
4857 break;
4858 }
4859
4860#ifdef ANI_BUS_TYPE_SDIO
4861 /* Now Open SAL */
4862 status = WLANSAL_Open(pVosContext, 0);
4863
4864 if(!VOS_IS_STATUS_SUCCESS(status))
4865 {
4866 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to open SAL", __func__);
4867
4868 /* If unable to open, cleanup and return failure */
4869 vos_preClose( &pVosContext );
4870 ret_status = -1;
4871 break;
4872 }
4873#endif // ANI_BUS_TYPE_SDIO
4874
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004875#ifndef MODULE
4876 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
4877 */
4878 hdd_set_conparam((v_UINT_t)con_mode);
4879#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004880
4881 // Call our main init function
4882 if(hdd_wlan_startup(dev)) {
4883 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
4884 __func__);
4885#ifdef ANI_BUS_TYPE_SDIO
4886 WLANSAL_Close(pVosContext);
4887#endif // ANI_BUS_TYPE_SDIO
4888 vos_preClose( &pVosContext );
4889 ret_status = -1;
4890 break;
4891 }
4892
4893 /* Cancel the vote for XO Core ON
4894 * This is done here for safety purposes in case we re-initialize without turning
4895 * it OFF in any error scenario.
4896 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004897 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07004898 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07004899 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07004900 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
4901 {
4902 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
4903 " Power consumed will be high\n");
4904 }
4905 } while (0);
4906
4907 if (0 != ret_status)
4908 {
4909 //Assert Deep sleep signal now to put Libra HW in lowest power state
4910 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
4911 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
4912
4913 //Vote off any PMIC voltage supplies
4914 vos_chipPowerDown(NULL, NULL, NULL);
4915#ifdef TIMER_MANAGER
4916 vos_timer_exit();
4917#endif
4918#ifdef MEMORY_DEBUG
4919 vos_mem_exit();
4920#endif
4921
Sameer Thalappil50dc0092013-02-19 17:23:33 -08004922#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07004923 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07004924#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004925 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
4926 }
4927 else
4928 {
4929 //Send WLAN UP indication to Nlink Service
4930 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
4931
4932 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
4933
4934 }
4935
4936 EXIT();
4937
4938 return ret_status;
4939}
4940
Jeff Johnson32d95a32012-09-10 13:15:23 -07004941/**---------------------------------------------------------------------------
4942
4943 \brief hdd_module_init() - Init Function
4944
4945 This is the driver entry point (invoked when module is loaded using insmod)
4946
4947 \param - None
4948
4949 \return - 0 for success, non zero for failure
4950
4951 --------------------------------------------------------------------------*/
4952#ifdef MODULE
4953static int __init hdd_module_init ( void)
4954{
4955 return hdd_driver_init();
4956}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004957#else /* #ifdef MODULE */
4958static int __init hdd_module_init ( void)
4959{
4960 /* Driver initialization is delayed to fwpath_changed_handler */
4961 return 0;
4962}
Jeff Johnson32d95a32012-09-10 13:15:23 -07004963#endif /* #ifdef MODULE */
4964
Jeff Johnson295189b2012-06-20 16:38:30 -07004965
4966/**---------------------------------------------------------------------------
4967
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004968 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07004969
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004970 This is the driver exit point (invoked when module is unloaded using rmmod
4971 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07004972
4973 \param - None
4974
4975 \return - None
4976
4977 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07004978static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07004979{
4980 hdd_context_t *pHddCtx = NULL;
4981 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004982
4983 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
4984
4985 //Get the global vos context
4986 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
4987
4988 if(!pVosContext)
4989 {
4990 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
4991 goto done;
4992 }
4993
4994 //Get the HDD context.
4995 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
4996
4997 if(!pHddCtx)
4998 {
4999 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
5000 }
5001 else
5002 {
Jeff Johnsone7245742012-09-05 17:12:55 -07005003 /* module exit should never proceed if SSR is not completed */
Jeff Johnson295189b2012-06-20 16:38:30 -07005004 while(isWDresetInProgress()){
Jeff Johnsone7245742012-09-05 17:12:55 -07005005 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__);
5006 msleep(1000);
Jeff Johnson295189b2012-06-20 16:38:30 -07005007 }
5008
5009 pHddCtx->isLoadUnloadInProgress = TRUE;
5010 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
5011
5012 //Do all the cleanup before deregistering the driver
5013 hdd_wlan_exit(pHddCtx);
5014 }
5015
5016#ifdef ANI_BUS_TYPE_SDIO
5017 WLANSAL_Close(pVosContext);
5018#endif // ANI_BUS_TYPE_SDIO
5019
5020 vos_preClose( &pVosContext );
5021
5022#ifdef TIMER_MANAGER
5023 vos_timer_exit();
5024#endif
5025#ifdef MEMORY_DEBUG
5026 vos_mem_exit();
5027#endif
5028
5029done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08005030#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07005031 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07005032#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005033 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
5034}
5035
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005036/**---------------------------------------------------------------------------
5037
5038 \brief hdd_module_exit() - Exit function
5039
5040 This is the driver exit point (invoked when module is unloaded using rmmod)
5041
5042 \param - None
5043
5044 \return - None
5045
5046 --------------------------------------------------------------------------*/
5047static void __exit hdd_module_exit(void)
5048{
5049 hdd_driver_exit();
5050}
5051
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005052#ifdef MODULE
5053static int fwpath_changed_handler(const char *kmessage,
5054 struct kernel_param *kp)
5055{
5056 /* nothing to do when driver is DLKM */
5057 return 0;
5058}
5059
5060static int con_mode_handler(const char *kmessage,
5061 struct kernel_param *kp)
5062{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07005063 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005064}
5065#else /* #ifdef MODULE */
5066/**---------------------------------------------------------------------------
5067
5068 \brief fwpath_changed_handler() - Handler Function
5069
5070 This is the driver entry point
5071 - delayed driver initialization when driver is statically linked
5072 - invoked when module parameter fwpath is modified from userpspace to signal
5073 initializing the WLAN driver
5074
5075 \return - 0 for success, non zero for failure
5076
5077 --------------------------------------------------------------------------*/
5078static int fwpath_changed_handler(const char *kmessage,
5079 struct kernel_param *kp)
5080{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005081 int ret_status;
5082
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005083 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005084 ret_status = hdd_driver_init();
5085 wlan_hdd_inited = ret_status ? 0 : 1;
5086 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005087 }
5088
5089 hdd_driver_exit();
5090
5091 msleep(200);
5092
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07005093 ret_status = hdd_driver_init();
5094 wlan_hdd_inited = ret_status ? 0 : 1;
5095 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005096}
5097
Jeff Johnson295189b2012-06-20 16:38:30 -07005098/**---------------------------------------------------------------------------
5099
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005100 \brief con_mode_handler() -
5101
5102 Handler function for module param con_mode when it is changed by userspace
5103 Dynamically linked - do nothing
5104 Statically linked - exit and init driver, as in rmmod and insmod
5105
5106 \param -
5107
5108 \return -
5109
5110 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005111static int con_mode_handler(const char *kmessage,
5112 struct kernel_param *kp)
5113{
5114 int ret = param_set_int(kmessage, kp);
5115
5116 if (ret)
5117 return ret;
5118
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07005119 return fwpath_changed_handler(kmessage, kp);
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005120}
5121#endif /* #ifdef MODULE */
5122
5123/**---------------------------------------------------------------------------
5124
Jeff Johnson295189b2012-06-20 16:38:30 -07005125 \brief hdd_get_conparam() -
5126
5127 This is the driver exit point (invoked when module is unloaded using rmmod)
5128
5129 \param - None
5130
5131 \return - tVOS_CON_MODE
5132
5133 --------------------------------------------------------------------------*/
5134tVOS_CON_MODE hdd_get_conparam ( void )
5135{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005136#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07005137 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005138#else
5139 return (tVOS_CON_MODE)curr_con_mode;
5140#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005141}
5142void hdd_set_conparam ( v_UINT_t newParam )
5143{
5144 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005145#ifndef MODULE
5146 curr_con_mode = con_mode;
5147#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005148}
5149/**---------------------------------------------------------------------------
5150
5151 \brief hdd_softap_sta_deauth() - function
5152
5153 This to take counter measure to handle deauth req from HDD
5154
5155 \param - pAdapter - Pointer to the HDD
5156
5157 \param - enable - boolean value
5158
5159 \return - None
5160
5161 --------------------------------------------------------------------------*/
5162
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005163VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07005164{
Jeff Johnson295189b2012-06-20 16:38:30 -07005165 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005166 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07005167#ifdef FEATURE_WLAN_NON_INTEGRATED_SOC
5168 tHalHandle hHalHandle;
5169#endif
5170
5171 ENTER();
5172
5173 hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5174
5175 //Ignore request to deauth bcmc station
5176 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005177 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005178
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005179 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07005180
5181 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08005182 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07005183}
5184
5185/**---------------------------------------------------------------------------
5186
5187 \brief hdd_softap_sta_disassoc() - function
5188
5189 This to take counter measure to handle deauth req from HDD
5190
5191 \param - pAdapter - Pointer to the HDD
5192
5193 \param - enable - boolean value
5194
5195 \return - None
5196
5197 --------------------------------------------------------------------------*/
5198
5199void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
5200{
5201 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5202
5203 ENTER();
5204
5205 hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5206
5207 //Ignore request to disassoc bcmc station
5208 if( pDestMacAddress[0] & 0x1 )
5209 return;
5210
5211 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
5212}
5213
5214void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
5215{
5216 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
5217
5218 ENTER();
5219
5220 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
5221
5222 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
5223}
5224
Jeff Johnson295189b2012-06-20 16:38:30 -07005225/**---------------------------------------------------------------------------
5226 *
5227 * \brief hdd_get__concurrency_mode() -
5228 *
5229 *
5230 * \param - None
5231 *
5232 * \return - CONCURRENCY MODE
5233 *
5234 * --------------------------------------------------------------------------*/
5235tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
5236{
5237 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
5238 hdd_context_t *pHddCtx;
5239
5240 if (NULL != pVosContext)
5241 {
5242 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
5243 if (NULL != pHddCtx)
5244 {
5245 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
5246 }
5247 }
5248
5249 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005250 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005251 return VOS_STA;
5252}
5253
5254/* Decide whether to allow/not the apps power collapse.
5255 * Allow apps power collapse if we are in connected state.
5256 * if not, allow only if we are in IMPS */
5257v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
5258{
5259 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08005260 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07005261 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5262 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5263 hdd_adapter_t *pAdapter = NULL;
5264 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08005265 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005266
5267#ifdef WLAN_SOFTAP_FEATURE
5268 if (VOS_STA_SAP_MODE == hdd_get_conparam())
5269 return TRUE;
5270#endif
5271
Yathish9f22e662012-12-10 14:21:35 -08005272 concurrent_state = hdd_get_concurrency_mode();
5273
5274#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
5275 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
5276 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
5277 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
5278 return TRUE;
5279#endif
5280
Jeff Johnson295189b2012-06-20 16:38:30 -07005281 /*loop through all adapters. TBD fix for Concurrency */
5282 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5283 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5284 {
5285 pAdapter = pAdapterNode->pAdapter;
5286 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
5287 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5288 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005289 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08005291 && pmcState != STOPPED && pmcState != STANDBY)) ||
5292 (eANI_BOOLEAN_TRUE == scanRspPending))
Jeff Johnson295189b2012-06-20 16:38:30 -07005293 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08005294 hddLog( LOGE, "%s: do not allow APPS power collapse-"
5295 "pmcState = %d scanRspPending = %d",
5296 __func__, pmcState, scanRspPending );
Jeff Johnson295189b2012-06-20 16:38:30 -07005297 return FALSE;
5298 }
5299 }
5300 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5301 pAdapterNode = pNext;
5302 }
5303 return TRUE;
5304}
5305
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08005306/* Decides whether to send suspend notification to Riva
5307 * if any adapter is in BMPS; then it is required */
5308v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
5309{
5310 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
5311 hdd_config_t *pConfig = pHddCtx->cfg_ini;
5312
5313 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
5314 {
5315 return TRUE;
5316 }
5317 return FALSE;
5318}
5319
Jeff Johnson295189b2012-06-20 16:38:30 -07005320void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5321{
5322 switch(mode)
5323 {
5324 case WLAN_HDD_INFRA_STATION:
5325#ifdef WLAN_FEATURE_P2P
5326 case WLAN_HDD_P2P_CLIENT:
5327 case WLAN_HDD_P2P_GO:
5328#endif
5329 case WLAN_HDD_SOFTAP:
Jeff Johnsone7245742012-09-05 17:12:55 -07005330 pHddCtx->concurrency_mode |= (1 << mode);
5331 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07005332 break;
5333 default:
5334 break;
5335
5336 }
5337 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5338 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5339}
5340
5341
5342void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
5343{
5344 switch(mode)
5345 {
5346 case WLAN_HDD_INFRA_STATION:
5347#ifdef WLAN_FEATURE_P2P
5348 case WLAN_HDD_P2P_CLIENT:
5349 case WLAN_HDD_P2P_GO:
5350#endif
5351 case WLAN_HDD_SOFTAP:
5352 pHddCtx->no_of_sessions[mode]--;
5353 if (!(pHddCtx->no_of_sessions[mode]))
5354 pHddCtx->concurrency_mode &= (~(1 << mode));
5355 break;
5356 default:
5357 break;
5358 }
5359 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
5360 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
5361}
5362
Jeff Johnsone7245742012-09-05 17:12:55 -07005363/**---------------------------------------------------------------------------
5364 *
5365 * \brief wlan_hdd_restart_init
5366 *
5367 * This function initalizes restart timer/flag. An internal function.
5368 *
5369 * \param - pHddCtx
5370 *
5371 * \return - None
5372 *
5373 * --------------------------------------------------------------------------*/
5374
5375static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
5376{
5377 /* Initialize */
5378 pHddCtx->hdd_restart_retries = 0;
5379 atomic_set(&pHddCtx->isRestartInProgress, 0);
5380 vos_timer_init(&pHddCtx->hdd_restart_timer,
5381 VOS_TIMER_TYPE_SW,
5382 wlan_hdd_restart_timer_cb,
5383 pHddCtx);
5384}
5385/**---------------------------------------------------------------------------
5386 *
5387 * \brief wlan_hdd_restart_deinit
5388 *
5389 * This function cleans up the resources used. An internal function.
5390 *
5391 * \param - pHddCtx
5392 *
5393 * \return - None
5394 *
5395 * --------------------------------------------------------------------------*/
5396
5397static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
5398{
5399
5400 VOS_STATUS vos_status;
5401 /* Block any further calls */
5402 atomic_set(&pHddCtx->isRestartInProgress, 1);
5403 /* Cleanup */
5404 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
5405 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005406 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005407 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
5408 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07005409 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07005410
5411}
5412
5413/**---------------------------------------------------------------------------
5414 *
5415 * \brief wlan_hdd_framework_restart
5416 *
5417 * This function uses a cfg80211 API to start a framework initiated WLAN
5418 * driver module unload/load.
5419 *
5420 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
5421 *
5422 *
5423 * \param - pHddCtx
5424 *
5425 * \return - VOS_STATUS_SUCCESS: Success
5426 * VOS_STATUS_E_EMPTY: Adapter is Empty
5427 * VOS_STATUS_E_NOMEM: No memory
5428
5429 * --------------------------------------------------------------------------*/
5430
5431static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
5432{
5433 VOS_STATUS status = VOS_STATUS_SUCCESS;
5434 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5435 int len = (sizeof (struct ieee80211_mgmt));
5436 struct ieee80211_mgmt *mgmt = NULL;
5437
5438 /* Prepare the DEAUTH managment frame with reason code */
5439 mgmt = kzalloc(len, GFP_KERNEL);
5440 if(mgmt == NULL)
5441 {
5442 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Jeff Johnson1250df42012-12-10 14:31:52 -08005443 "%s: memory allocation failed (%d bytes)", __func__, len);
Jeff Johnsone7245742012-09-05 17:12:55 -07005444 return VOS_STATUS_E_NOMEM;
5445 }
5446 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
5447
5448 /* Iterate over all adapters/devices */
5449 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5450 do
5451 {
5452 if( (status == VOS_STATUS_SUCCESS) &&
5453 pAdapterNode &&
5454 pAdapterNode->pAdapter)
5455 {
5456 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
5457 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
5458 pAdapterNode->pAdapter->dev->name,
5459 pAdapterNode->pAdapter->device_mode,
5460 pHddCtx->hdd_restart_retries + 1);
5461 /*
5462 * CFG80211 event to restart the driver
5463 *
5464 * 'cfg80211_send_unprot_deauth' sends a
5465 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
5466 * of SME(Linux Kernel) state machine.
5467 *
5468 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
5469 * the driver.
5470 *
5471 */
5472
5473 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
5474 }
5475 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5476 pAdapterNode = pNext;
5477 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
5478
5479
5480 /* Free the allocated management frame */
5481 kfree(mgmt);
5482
5483 /* Retry until we unload or reach max count */
5484 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
5485 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
5486
5487 return status;
5488
5489}
5490/**---------------------------------------------------------------------------
5491 *
5492 * \brief wlan_hdd_restart_timer_cb
5493 *
5494 * Restart timer callback. An internal function.
5495 *
5496 * \param - User data:
5497 *
5498 * \return - None
5499 *
5500 * --------------------------------------------------------------------------*/
5501
5502void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
5503{
5504 hdd_context_t *pHddCtx = usrDataForCallback;
5505 wlan_hdd_framework_restart(pHddCtx);
5506 return;
5507
5508}
5509
5510
5511/**---------------------------------------------------------------------------
5512 *
5513 * \brief wlan_hdd_restart_driver
5514 *
5515 * This function sends an event to supplicant to restart the WLAN driver.
5516 *
5517 * This function is called from vos_wlanRestart.
5518 *
5519 * \param - pHddCtx
5520 *
5521 * \return - VOS_STATUS_SUCCESS: Success
5522 * VOS_STATUS_E_EMPTY: Adapter is Empty
5523 * VOS_STATUS_E_ALREADY: Request already in progress
5524
5525 * --------------------------------------------------------------------------*/
5526VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
5527{
5528 VOS_STATUS status = VOS_STATUS_SUCCESS;
5529
5530 /* A tight check to make sure reentrancy */
5531 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
5532 {
5533 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
5534 "%s: WLAN restart is already in progress", __func__);
5535
5536 return VOS_STATUS_E_ALREADY;
5537 }
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005538 /* when WLAN driver is statically linked, then invoke SSR by sending
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005539 * the reset interrupt. If it is DLKM, then use restart API
5540 */
5541#ifdef MODULE
Jeff Johnsone7245742012-09-05 17:12:55 -07005542 status = wlan_hdd_framework_restart(pHddCtx);
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005543#else
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005544#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07005545 wcnss_reset_intr();
5546#endif
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08005547#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07005548
Jeff Johnsone7245742012-09-05 17:12:55 -07005549 return status;
5550}
5551
5552
Jeff Johnson295189b2012-06-20 16:38:30 -07005553//Register the module init/exit functions
5554module_init(hdd_module_init);
5555module_exit(hdd_module_exit);
5556
5557MODULE_LICENSE("Dual BSD/GPL");
5558MODULE_AUTHOR("Qualcomm Atheros, Inc.");
5559MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
5560
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07005561module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
5562 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07005563
5564module_param_call(fwpath, fwpath_changed_handler, param_get_string, fwpath,
5565 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);