blob: 4a571411111e2d3ea9da560f69828102184460f9 [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>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
112#include <mach/subsystem_restart.h>
113#include <wlan_hdd_hostapd.h>
114#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700115#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "wlan_hdd_dev_pwr.h"
117#ifdef WLAN_BTAMP_FEATURE
118#include "bap_hdd_misc.h"
119#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700120#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800122#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530123#ifdef FEATURE_WLAN_TDLS
124#include "wlan_hdd_tdls.h"
125#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700126#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700127
128#ifdef MODULE
129#define WLAN_MODULE_NAME module_name(THIS_MODULE)
130#else
131#define WLAN_MODULE_NAME "wlan"
132#endif
133
134#ifdef TIMER_MANAGER
135#define TIMER_MANAGER_STR " +TIMER_MANAGER"
136#else
137#define TIMER_MANAGER_STR ""
138#endif
139
140#ifdef MEMORY_DEBUG
141#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
142#else
143#define MEMORY_DEBUG_STR ""
144#endif
145
146/* the Android framework expects this param even though we don't use it */
147#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700148static char fwpath_buffer[BUF_LEN];
149static struct kparam_string fwpath = {
150 .string = fwpath_buffer,
151 .maxlen = BUF_LEN,
152};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700153#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700154static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700155#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700156
Jeff Johnsone7245742012-09-05 17:12:55 -0700157/*
158 * The rate at which the driver sends RESTART event to supplicant
159 * once the function 'vos_wlanRestart()' is called
160 *
161 */
162#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
163#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700164
165/*
166 * Size of Driver command strings from upper layer
167 */
168#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
169#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
170
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700171/*
172 * Driver miracast parameters 0-Disabled
173 * 1-Source, 2-Sink
174 */
175#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
176#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
177
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800178#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700179static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700180#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700181/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700182static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700183
184//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700185static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
186static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
187static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
188void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800189void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700190
Jeff Johnson295189b2012-06-20 16:38:30 -0700191v_U16_t hdd_select_queue(struct net_device *dev,
192 struct sk_buff *skb);
193
194#ifdef WLAN_FEATURE_PACKET_FILTERING
195static void hdd_set_multicast_list(struct net_device *dev);
196#endif
197
198void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700199int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700200
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);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700205static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
206 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
207 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700208static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
209 tANI_U8 *pTargetApBssid,
210 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800211#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700212static int hdd_netdev_notifier_call(struct notifier_block * nb,
213 unsigned long state,
214 void *ndev)
215{
216 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700217 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700218 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700219#ifdef WLAN_BTAMP_FEATURE
220 VOS_STATUS status;
221 hdd_context_t *pHddCtx;
222#endif
223
224 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700225 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700226 (strncmp(dev->name, "p2p", 3)))
227 return NOTIFY_DONE;
228
229 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700230 return NOTIFY_DONE;
231
Jeff Johnson295189b2012-06-20 16:38:30 -0700232 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700233 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700234
Jeff Johnson27cee452013-03-27 11:10:24 -0700235 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700236 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800237 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700238 VOS_ASSERT(0);
239 return NOTIFY_DONE;
240 }
241
Jeff Johnson27cee452013-03-27 11:10:24 -0700242 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
243 if (NULL == pHddCtx)
244 {
245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
246 VOS_ASSERT(0);
247 return NOTIFY_DONE;
248 }
249
250 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
251 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700252
253 switch (state) {
254 case NETDEV_REGISTER:
255 break;
256
257 case NETDEV_UNREGISTER:
258 break;
259
260 case NETDEV_UP:
261 break;
262
263 case NETDEV_DOWN:
264 break;
265
266 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700267 if(TRUE == pAdapter->isLinkUpSvcNeeded)
268 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700269 break;
270
271 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700272 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700273 {
274 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800275 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530276 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700277 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800278 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700279 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
280 if(!result)
281 {
282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800283 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700284 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700285 }
286 }
287 else
288 {
289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700290 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700291 }
292#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700293 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700294 status = WLANBAP_StopAmp();
295 if(VOS_STATUS_SUCCESS != status )
296 {
297 pHddCtx->isAmpAllowed = VOS_TRUE;
298 hddLog(VOS_TRACE_LEVEL_FATAL,
299 "%s: Failed to stop AMP", __func__);
300 }
301 else
302 {
303 //a state m/c implementation in PAL is TBD to avoid this delay
304 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700305 if ( pHddCtx->isAmpAllowed )
306 {
307 WLANBAP_DeregisterFromHCI();
308 pHddCtx->isAmpAllowed = VOS_FALSE;
309 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 }
311#endif //WLAN_BTAMP_FEATURE
312 break;
313
314 default:
315 break;
316 }
317
318 return NOTIFY_DONE;
319}
320
321struct notifier_block hdd_netdev_notifier = {
322 .notifier_call = hdd_netdev_notifier_call,
323};
324
325/*---------------------------------------------------------------------------
326 * Function definitions
327 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700328void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
329void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700330//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700331static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700332#ifndef MODULE
333/* current con_mode - used only for statically linked driver
334 * con_mode is changed by userspace to indicate a mode change which will
335 * result in calling the module exit and init functions. The module
336 * exit function will clean up based on the value of con_mode prior to it
337 * being changed by userspace. So curr_con_mode records the current con_mode
338 * for exit when con_mode becomes the next mode for init
339 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700340static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700341#endif
342
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800343/**---------------------------------------------------------------------------
344
345 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
346
347 Called immediately after the cfg.ini is read in order to configure
348 the desired trace levels.
349
350 \param - moduleId - module whose trace level is being configured
351 \param - bitmask - bitmask of log levels to be enabled
352
353 \return - void
354
355 --------------------------------------------------------------------------*/
356static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
357{
358 wpt_tracelevel level;
359
360 /* if the bitmask is the default value, then a bitmask was not
361 specified in cfg.ini, so leave the logging level alone (it
362 will remain at the "compiled in" default value) */
363 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
364 {
365 return;
366 }
367
368 /* a mask was specified. start by disabling all logging */
369 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
370
371 /* now cycle through the bitmask until all "set" bits are serviced */
372 level = VOS_TRACE_LEVEL_FATAL;
373 while (0 != bitmask)
374 {
375 if (bitmask & 1)
376 {
377 vos_trace_setValue(moduleId, level, 1);
378 }
379 level++;
380 bitmask >>= 1;
381 }
382}
383
384
Jeff Johnson295189b2012-06-20 16:38:30 -0700385/**---------------------------------------------------------------------------
386
387 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
388
389 Called immediately after the cfg.ini is read in order to configure
390 the desired trace levels in the WDI.
391
392 \param - moduleId - module whose trace level is being configured
393 \param - bitmask - bitmask of log levels to be enabled
394
395 \return - void
396
397 --------------------------------------------------------------------------*/
398static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
399{
400 wpt_tracelevel level;
401
402 /* if the bitmask is the default value, then a bitmask was not
403 specified in cfg.ini, so leave the logging level alone (it
404 will remain at the "compiled in" default value) */
405 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
406 {
407 return;
408 }
409
410 /* a mask was specified. start by disabling all logging */
411 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
412
413 /* now cycle through the bitmask until all "set" bits are serviced */
414 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
415 while (0 != bitmask)
416 {
417 if (bitmask & 1)
418 {
419 wpalTraceSetLevel(moduleId, level, 1);
420 }
421 level++;
422 bitmask >>= 1;
423 }
424}
Jeff Johnson295189b2012-06-20 16:38:30 -0700425
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530426/*
427 * FUNCTION: wlan_hdd_validate_context
428 * This function is used to check the HDD context
429 */
430int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
431{
432 ENTER();
433
434 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
435 {
436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
437 "%s: HDD context is Null", __func__);
438 return -ENODEV;
439 }
440
441 if (pHddCtx->isLogpInProgress)
442 {
443 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
444 "%s: LOGP in Progress. Ignore!!!", __func__);
445 return -EAGAIN;
446 }
447
448 if (pHddCtx->isLoadUnloadInProgress)
449 {
450 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
451 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
452 return -EAGAIN;
453 }
454 return 0;
455}
456
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530457void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
458{
459 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
460 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
461 hdd_config_t *cfg_param;
462 eCsrPhyMode phyMode;
463
464 if (NULL == pHddCtx)
465 {
466 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
467 "HDD Context is null !!");
468 return ;
469 }
470
471 cfg_param = pHddCtx->cfg_ini;
472
473 if (NULL == cfg_param)
474 {
475 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
476 "cfg_params not available !!");
477 return ;
478 }
479
480 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
481
482 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
483 {
484 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
485 (eCSR_DOT11_MODE_11ac == phyMode) ||
486 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
487 {
488 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
489 "Setting phymode to 11n!!");
490 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
491 }
492 }
493 else
494 {
495 /*New country Supports 11ac as well resetting value back from .ini*/
496 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
497 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
498 return ;
499 }
500
501 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
502 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
503 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
504 {
505 VOS_STATUS vosStatus;
506
507 // need to issue a disconnect to CSR.
508 INIT_COMPLETION(pAdapter->disconnect_comp_var);
509 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
510 pAdapter->sessionId,
511 eCSR_DISCONNECT_REASON_UNSPECIFIED );
512
513 if (VOS_STATUS_SUCCESS == vosStatus)
514 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
515 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
516
517 }
518}
519
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700520void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
521{
522 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
523 hdd_config_t *cfg_param;
524
525 if (NULL == pHddCtx)
526 {
527 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
528 "HDD Context is null !!");
529 return ;
530 }
531
532 cfg_param = pHddCtx->cfg_ini;
533
534 if (NULL == cfg_param)
535 {
536 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
537 "cfg_params not available !!");
538 return ;
539 }
540
541 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
542 {
543 /*New country doesn't support DFS */
544 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
545 }
546 else
547 {
548 /*New country Supports DFS as well resetting value back from .ini*/
549 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
550 }
551
552}
553
Rajeev79dbe4c2013-10-05 11:03:42 +0530554#ifdef FEATURE_WLAN_BATCH_SCAN
555
556/**---------------------------------------------------------------------------
557
558 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
559 input string
560
561 This function extracts assigned integer from string in below format:
562 "STRING=10" : extracts integer 10 from this string
563
564 \param - pInPtr Pointer to input string
565 \param - base Base for string to int conversion(10 for decimal 16 for hex)
566 \param - pOutPtr Pointer to variable in which extracted integer needs to be
567 assigned
568 \param - pLastArg to tell whether it is last arguement in input string or
569 not
570
571 \return - NULL for failure cases
572 pointer to next arguement in input string for success cases
573 --------------------------------------------------------------------------*/
574static tANI_U8 *
575hdd_extract_assigned_int_from_str
576(
577 tANI_U8 *pInPtr,
578 tANI_U8 base,
579 tANI_U32 *pOutPtr,
580 tANI_U8 *pLastArg
581)
582{
583 int tempInt;
584 int v = 0;
585 char buf[32];
586 int val = 0;
587 *pLastArg = FALSE;
588
589 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
590 if (NULL == pInPtr)
591 {
592 return NULL;
593 }
594
595 pInPtr++;
596
597 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
598
599 val = sscanf(pInPtr, "%32s ", buf);
600 if (val < 0 && val > strlen(pInPtr))
601 {
602 return NULL;
603 }
604 pInPtr += val;
605 v = kstrtos32(buf, base, &tempInt);
606 if (v < 0)
607 {
608 return NULL;
609 }
610 *pOutPtr = tempInt;
611
612 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
613 if (NULL == pInPtr)
614 {
615 *pLastArg = TRUE;
616 return NULL;
617 }
618 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
619
620 return pInPtr;
621}
622
623/**---------------------------------------------------------------------------
624
625 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
626 input string
627
628 This function extracts assigned character from string in below format:
629 "STRING=A" : extracts char 'A' from this string
630
631 \param - pInPtr Pointer to input string
632 \param - pOutPtr Pointer to variable in which extracted char needs to be
633 assigned
634 \param - pLastArg to tell whether it is last arguement in input string or
635 not
636
637 \return - NULL for failure cases
638 pointer to next arguement in input string for success cases
639 --------------------------------------------------------------------------*/
640static tANI_U8 *
641hdd_extract_assigned_char_from_str
642(
643 tANI_U8 *pInPtr,
644 tANI_U8 *pOutPtr,
645 tANI_U8 *pLastArg
646)
647{
648 *pLastArg = FALSE;
649
650 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
651 if (NULL == pInPtr)
652 {
653 return NULL;
654 }
655
656 pInPtr++;
657
658 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
659
660 *pOutPtr = *pInPtr;
661
662 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
663 if (NULL == pInPtr)
664 {
665 *pLastArg = TRUE;
666 return NULL;
667 }
668 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
669
670 return pInPtr;
671}
672
673
674/**---------------------------------------------------------------------------
675
676 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
677
678 This function parses set batch scan command in below format:
679 WLS_BATCHING_SET <space> followed by below arguements
680 "SCANFREQ=XX" : Optional defaults to 30 sec
681 "MSCAN=XX" : Required number of scans to attempt to batch
682 "BESTN=XX" : Best Network (RSSI) defaults to 16
683 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
684 A. implies only 5 GHz , B. implies only 2.4GHz
685 "RTT=X" : optional defaults to 0
686 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
687 error
688
689 For example input commands:
690 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
691 translated into set batch scan with following parameters:
692 a) Frequence 60 seconds
693 b) Batch 10 scans together
694 c) Best RSSI to be 20
695 d) 5GHz band only
696 e) RTT is equal to 0
697
698 \param - pValue Pointer to input channel list
699 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
700
701 \return - 0 for success non-zero for failure
702
703 --------------------------------------------------------------------------*/
704static int
705hdd_parse_set_batchscan_command
706(
707 tANI_U8 *pValue,
708 tSirSetBatchScanReq *pHddSetBatchScanReq
709)
710{
711 tANI_U8 *inPtr = pValue;
712 tANI_U8 val = 0;
713 tANI_U8 lastArg = 0;
714
715 /*initialize default values*/
716 pHddSetBatchScanReq->scanFrequency = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
717 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
718 pHddSetBatchScanReq->rtt = 0;
719 pHddSetBatchScanReq->bestNetwork = HDD_SET_BATCH_SCAN_BEST_NETWORK;
720
721 /*go to space after WLS_BATCHING_SET command*/
722 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
723 /*no argument after the command*/
724 if (NULL == inPtr)
725 {
726 return -EINVAL;
727 }
728
729 /*no space after the command*/
730 else if (SPACE_ASCII_VALUE != *inPtr)
731 {
732 return -EINVAL;
733 }
734
735 /*removing empty spaces*/
736 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
737
738 /*no argument followed by spaces*/
739 if ('\0' == *inPtr)
740 {
741 return -EINVAL;
742 }
743
744 /*check and parse SCANFREQ*/
745 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
746 {
747 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
748 &pHddSetBatchScanReq->scanFrequency, &lastArg);
749 if ( (NULL == inPtr) || (TRUE == lastArg))
750 {
751 return -EINVAL;
752 }
753 }
754
755 /*check and parse MSCAN*/
756 if ((strncmp(inPtr, "MSCAN", 5) == 0))
757 {
758 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
759 &pHddSetBatchScanReq->numberOfScansToBatch, &lastArg);
760 if (TRUE == lastArg)
761 {
762 goto done;
763 }
764 else if (NULL == inPtr)
765 {
766 return -EINVAL;
767 }
768 }
769 else
770 {
771 return -EINVAL;
772 }
773
774 /*check and parse BESTN*/
775 if ((strncmp(inPtr, "BESTN", 5) == 0))
776 {
777 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
778 &pHddSetBatchScanReq->bestNetwork, &lastArg);
779 if (TRUE == lastArg)
780 {
781 goto done;
782 }
783 else if (NULL == inPtr)
784 {
785 return -EINVAL;
786 }
787 }
788
789 /*check and parse CHANNEL*/
790 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
791 {
792 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
793 if (TRUE == lastArg)
794 {
795 goto done;
796 }
797 else if (NULL == inPtr)
798 {
799 return -EINVAL;
800 }
801 if (('A' == val) || ('a' == val))
802 {
803 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
804 }
805 else if (('B' == val) || ('b' == val))
806 {
807 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
808 }
809 else
810 {
811 return -EINVAL;
812 }
813 }
814
815 /*check and parse RTT*/
816 if ((strncmp(inPtr, "RTT", 3) == 0))
817 {
818 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
819 &pHddSetBatchScanReq->rtt, &lastArg);
820 if (TRUE == lastArg)
821 {
822 goto done;
823 }
824 if (NULL == inPtr)
825 {
826 return -EINVAL;
827 }
828 }
829
830
831done:
832
833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
834 "Received WLS_BATCHING_SET with SCANFREQ=%d "
835 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
836 pHddSetBatchScanReq->scanFrequency,
837 pHddSetBatchScanReq->numberOfScansToBatch,
838 pHddSetBatchScanReq->bestNetwork,
839 pHddSetBatchScanReq->rfBand,
840 pHddSetBatchScanReq->rtt);
841
842 return 0;
843}/*End of hdd_parse_set_batchscan_command*/
844
845/**---------------------------------------------------------------------------
846
847 \brief hdd_set_batch_scan_req_callback () - This function is called after
848 receiving set batch scan response from FW and it saves set batch scan
849 response data FW to HDD context and sets the completion event on
850 which hdd_ioctl is waiting
851
852 \param - callbackContext Pointer to HDD adapter
853 \param - pRsp Pointer to set batch scan response data received from FW
854
855 \return - nothing
856
857 --------------------------------------------------------------------------*/
858static void hdd_set_batch_scan_req_callback
859(
860 void *callbackContext,
861 tSirSetBatchScanRsp *pRsp
862)
863{
864 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
865 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
866
867 /*sanity check*/
868 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
869 {
870 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
871 "%s: Invalid pAdapter magic", __func__);
872 VOS_ASSERT(0);
873 return;
874 }
875 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
876
877 /*save set batch scan response*/
878 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
879
880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
881 "Received set batch scan rsp from FW with nScansToBatch=%d",
882 pHddSetBatchScanRsp->nScansToBatch);
883
884 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
885 complete(&pAdapter->hdd_set_batch_scan_req_var);
886
887 return;
888}/*End of hdd_set_batch_scan_req_callback*/
889
890
891/**---------------------------------------------------------------------------
892
893 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
894 info in hdd batch scan response queue
895
896 \param - pAdapter Pointer to hdd adapter
897 \param - pAPMetaInfo Pointer to access point meta info
898 \param - scanId scan ID of batch scan response
899 \param - isLastAp tells whether AP is last AP in batch scan response or not
900
901 \return - nothing
902
903 --------------------------------------------------------------------------*/
904static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
905 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
906{
907 tHddBatchScanRsp *pHead;
908 tHddBatchScanRsp *pNode;
909 tHddBatchScanRsp *pPrev;
910 tHddBatchScanRsp *pTemp;
911 tANI_U8 ssidLen;
912
913 /*head of hdd batch scan response queue*/
914 pHead = pAdapter->pBatchScanRsp;
915
916 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
917 if (NULL == pNode)
918 {
919 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
920 "%s: Could not allocate memory", __func__);
921 VOS_ASSERT(0);
922 return;
923 }
924
925 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
926 sizeof(pNode->ApInfo.bssid));
927 ssidLen = strlen(pApMetaInfo->ssid);
928 if (SIR_MAX_SSID_SIZE < ssidLen)
929 {
930 /*invalid scan result*/
931 vos_mem_free(pNode);
932 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
933 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
934 return;
935 }
936 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
937 /*null terminate ssid*/
938 pNode->ApInfo.ssid[ssidLen] = '\0';
939 pNode->ApInfo.ch = pApMetaInfo->ch;
940 pNode->ApInfo.rssi = pApMetaInfo->rssi;
941 pNode->ApInfo.age = pApMetaInfo->timestamp;
942 pNode->ApInfo.batchId = scanId;
943 pNode->ApInfo.isLastAp = isLastAp;
944
945 pNode->pNext = NULL;
946 if (NULL == pHead)
947 {
948 pAdapter->pBatchScanRsp = pNode;
949 }
950 else
951 {
952 pTemp = pHead;
953 while (NULL != pTemp)
954 {
955 pPrev = pTemp;
956 pTemp = pTemp->pNext;
957 }
958 pPrev->pNext = pNode;
959 }
960
961 return;
962}/*End of hdd_populate_batch_scan_rsp_queue*/
963
964/**---------------------------------------------------------------------------
965
966 \brief hdd_batch_scan_result_ind_callback () - This function is called after
967 receiving batch scan response indication from FW. It saves get batch scan
968 response data in HDD batch scan response queue. This callback sets the
969 completion event on which hdd_ioctl is waiting only after getting complete
970 batch scan response data from FW
971
972 \param - callbackContext Pointer to HDD adapter
973 \param - pRsp Pointer to get batch scan response data received from FW
974
975 \return - nothing
976
977 --------------------------------------------------------------------------*/
978static void hdd_batch_scan_result_ind_callback
979(
980 void *callbackContext,
981 void *pRsp
982)
983{
984 v_BOOL_t isLastAp;
985 tANI_U32 numApMetaInfo;
986 tANI_U32 numberScanList;
987 tANI_U32 nextScanListOffset;
988 tANI_U32 nextApMetaInfoOffset;
989 hdd_adapter_t* pAdapter;
990 tpSirBatchScanList pScanList;
991 tpSirBatchScanNetworkInfo pApMetaInfo;
992 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
993 tSirSetBatchScanReq *pReq;
994
995 pAdapter = (hdd_adapter_t *)callbackContext;
996 /*sanity check*/
997 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
998 {
999 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1000 "%s: Invalid pAdapter magic", __func__);
1001 VOS_ASSERT(0);
1002 return;
1003 }
1004
1005 /*initialize locals*/
1006 pReq = &pAdapter->hddSetBatchScanReq;
1007 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1008 isLastAp = FALSE;
1009 numApMetaInfo = 0;
1010 numberScanList = 0;
1011 nextScanListOffset = 0;
1012 nextApMetaInfoOffset = 0;
1013 pScanList = NULL;
1014 pApMetaInfo = NULL;
1015
1016 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1017 {
1018 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1019 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1020 isLastAp = TRUE;
1021 goto done;
1022 }
1023
1024 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1026 "Batch scan rsp: numberScalList %d", numberScanList);
1027
1028 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1029 {
1030 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1031 "%s: numberScanList %d", __func__, numberScanList);
1032 isLastAp = TRUE;
1033 goto done;
1034 }
1035
1036 while (numberScanList)
1037 {
1038 pScanList = (tpSirBatchScanList)(pBatchScanRsp->scanResults +
1039 nextScanListOffset);
1040 if (NULL == pScanList)
1041 {
1042 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1043 "%s: pScanList is %p", __func__, pScanList);
1044 isLastAp = TRUE;
1045 goto done;
1046 }
1047 numApMetaInfo = pScanList->numNetworksInScanList;
1048 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1049 "Batch scan rsp: numApMetaInfo %d", numApMetaInfo);
1050
1051 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1052 {
1053 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1054 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1055 isLastAp = TRUE;
1056 goto done;
1057 }
1058
1059 while (numApMetaInfo)
1060 {
1061 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1062 nextApMetaInfoOffset);
1063 if (NULL == pApMetaInfo)
1064 {
1065 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1066 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1067 isLastAp = TRUE;
1068 goto done;
1069 }
1070 /*calculate AP age*/
1071 pApMetaInfo->timestamp =
1072 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1073
1074 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1075 "%s: bssId 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x "
1076 "ch %d rssi %d timestamp %d", __func__,
1077 pApMetaInfo->bssid[0],pApMetaInfo->bssid[1],
1078 pApMetaInfo->bssid[2],pApMetaInfo->bssid[3],
1079 pApMetaInfo->bssid[4],pApMetaInfo->bssid[5],
1080 pApMetaInfo->ch, pApMetaInfo->rssi,
1081 pApMetaInfo->timestamp);
1082
1083 /*mark last AP in batch scan response*/
1084 if ((TRUE == pBatchScanRsp->isLastResult) &&
1085 (1 == numberScanList) && (1 == numApMetaInfo))
1086 {
1087 isLastAp = TRUE;
1088 }
1089
1090 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1091 /*store batch scan repsonse in hdd queue*/
1092 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1093 pScanList->scanId, isLastAp);
1094 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1095
1096 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1097 numApMetaInfo--;
1098 }
1099
1100 nextScanListOffset += (sizeof(tSirBatchScanList) - (sizeof(tANI_U8)));
1101 numberScanList--;
1102 }
1103
1104done:
1105
1106 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1107 requested from hdd_ioctl*/
1108 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1109 (TRUE == isLastAp))
1110 {
1111 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1112 complete(&pAdapter->hdd_get_batch_scan_req_var);
1113 }
1114
1115 return;
1116}/*End of hdd_batch_scan_result_ind_callback*/
1117
1118/**---------------------------------------------------------------------------
1119
1120 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1121 response as per batch scan FR request format by putting proper markers
1122
1123 \param - pDest pointer to destination buffer
1124 \param - cur_len current length
1125 \param - tot_len total remaining size which can be written to user space
1126 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1127 \param - pAdapter Pointer to HDD adapter
1128
1129 \return - ret no of characters written
1130
1131 --------------------------------------------------------------------------*/
1132static tANI_U32
1133hdd_format_batch_scan_rsp
1134(
1135 tANI_U8 *pDest,
1136 tANI_U32 cur_len,
1137 tANI_U32 tot_len,
1138 tHddBatchScanRsp *pApMetaInfo,
1139 hdd_adapter_t* pAdapter
1140)
1141{
1142 tANI_U32 ret = 0;
1143 tANI_U32 rem_len = 0;
1144 tANI_U8 temp_len = 0;
1145 tANI_U8 temp_total_len = 0;
1146 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1147 tANI_U8 *pTemp = temp;
1148
1149 /*Batch scan reponse needs to be returned to user space in
1150 following format:
1151 "scancount=X\n" where X is the number of scans in current batch
1152 batch
1153 "trunc\n" optional present if current scan truncated
1154 "bssid=XX:XX:XX:XX:XX:XX\n"
1155 "ssid=XXXX\n"
1156 "freq=X\n" frequency in Mhz
1157 "level=XX\n"
1158 "age=X\n" ms
1159 "dist=X\n" cm (-1 if not available)
1160 "errror=X\n" (-1if not available)
1161 "====\n" (end of ap marker)
1162 "####\n" (end of scan marker)
1163 "----\n" (end of results)*/
1164 /*send scan result in above format to user space based on
1165 available length*/
1166 /*The GET response may have more data than the driver can return in its
1167 buffer. In that case the buffer should be filled to the nearest complete
1168 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1169 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1170 The final buffer should end with "----\n"*/
1171
1172 /*sanity*/
1173 if (cur_len > tot_len)
1174 {
1175 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1176 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1177 return 0;
1178 }
1179 else
1180 {
1181 rem_len = (tot_len - cur_len);
1182 }
1183
1184 /*end scan marker*/
1185 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1186 {
1187 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1188 pTemp += temp_len;
1189 temp_total_len += temp_len;
1190 }
1191
1192 /*bssid*/
1193 temp_len = snprintf(pTemp, sizeof(temp),
1194 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1195 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1196 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1197 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1198 pTemp += temp_len;
1199 temp_total_len += temp_len;
1200
1201 /*ssid*/
1202 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1203 pApMetaInfo->ApInfo.ssid);
1204 pTemp += temp_len;
1205 temp_total_len += temp_len;
1206
1207 /*freq*/
1208 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
1209 pApMetaInfo->ApInfo.ch);
1210 pTemp += temp_len;
1211 temp_total_len += temp_len;
1212
1213 /*level*/
1214 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1215 pApMetaInfo->ApInfo.rssi);
1216 pTemp += temp_len;
1217 temp_total_len += temp_len;
1218
1219 /*age*/
1220 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%ld\n",
1221 pApMetaInfo->ApInfo.age);
1222 pTemp += temp_len;
1223 temp_total_len += temp_len;
1224
1225 /*dist*/
1226 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1227 pTemp += temp_len;
1228 temp_total_len += temp_len;
1229
1230 /*error*/
1231 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1232 pTemp += temp_len;
1233 temp_total_len += temp_len;
1234
1235 /*end AP marker*/
1236 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1237 pTemp += temp_len;
1238 temp_total_len += temp_len;
1239
1240 /*last AP in batch scan response*/
1241 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1242 {
1243 /*end scan marker*/
1244 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1245 pTemp += temp_len;
1246 temp_total_len += temp_len;
1247
1248 /*end batch scan result marker*/
1249 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1250 pTemp += temp_len;
1251 temp_total_len += temp_len;
1252 }
1253
1254 if (temp_total_len < rem_len)
1255 {
1256 ret = temp_total_len + 1;
1257 strlcpy(pDest, temp, ret);
1258 pAdapter->isTruncated = FALSE;
1259 }
1260 else
1261 {
1262 pAdapter->isTruncated = TRUE;
1263 if (rem_len >= strlen("%%%%"))
1264 {
1265 ret = snprintf(pDest, strlen("%%%%"), "%%%%");
1266 }
1267 {
1268 ret = 0;
1269 }
1270 }
1271
1272 return ret;
1273
1274}/*End of hdd_format_batch_scan_rsp*/
1275
1276/**---------------------------------------------------------------------------
1277
1278 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1279 buffer starting with head of hdd batch scan response queue
1280
1281 \param - pAdapter Pointer to HDD adapter
1282 \param - pDest Pointer to user data buffer
1283 \param - cur_len current offset in user buffer
1284 \param - rem_len remaining no of bytes in user buffer
1285
1286 \return - number of bytes written in user buffer
1287
1288 --------------------------------------------------------------------------*/
1289
1290tANI_U32 hdd_populate_user_batch_scan_rsp
1291(
1292 hdd_adapter_t* pAdapter,
1293 tANI_U8 *pDest,
1294 tANI_U32 cur_len,
1295 tANI_U32 rem_len
1296)
1297{
1298 tHddBatchScanRsp *pHead;
1299 tHddBatchScanRsp *pPrev;
1300 tANI_U32 len;
1301
1302 pAdapter->prev_batch_id = 0;
1303 pAdapter->isTruncated = FALSE;
1304
1305 /*head of hdd batch scan response queue*/
1306 pHead = pAdapter->pBatchScanRsp;
1307 while (pHead)
1308 {
1309 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1310 pAdapter);
1311 pDest += len;
1312 cur_len += len;
1313 if(TRUE == pAdapter->isTruncated)
1314 {
1315 /*result is truncated return rest of scan rsp in next req*/
1316 cur_len = rem_len;
1317 break;
1318 }
1319 pPrev = pHead;
1320 pHead = pHead->pNext;
1321 pAdapter->pBatchScanRsp = pHead;
1322 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1323 vos_mem_free(pPrev);
1324 }
1325
1326 return cur_len;
1327}/*End of hdd_populate_user_batch_scan_rsp*/
1328
1329/**---------------------------------------------------------------------------
1330
1331 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1332 scan response data from HDD queue to user space
1333 It does following in detail:
1334 a) if HDD has enough data in its queue then it 1st copies data to user
1335 space and then send get batch scan indication message to FW. In this
1336 case it does not wait on any event and batch scan response data will
1337 be populated in HDD response queue in MC thread context after receiving
1338 indication from FW
1339 b) else send get batch scan indication message to FW and wait on an event
1340 which will be set once HDD receives complete batch scan response from
1341 FW and then this function returns batch scan response to user space
1342
1343 \param - pAdapter Pointer to HDD adapter
1344 \param - pPrivData Pointer to priv_data
1345
1346 \return - 0 for success -EFAULT for failure
1347
1348 --------------------------------------------------------------------------*/
1349
1350int hdd_return_batch_scan_rsp_to_user
1351(
1352 hdd_adapter_t* pAdapter,
1353 hdd_priv_data_t *pPrivData,
1354 tANI_U8 *command
1355)
1356{
1357 tANI_U8 *pDest;
1358 tANI_U32 count = 0;
1359 tANI_U32 len = 0;
1360 tANI_U32 cur_len = 0;
1361 tANI_U32 rem_len = 0;
1362 eHalStatus halStatus;
1363 unsigned long rc;
1364 tSirTriggerBatchScanResultInd *pReq;
1365
1366 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1367 pReq->param = 0;/*batch scan client*/
1368 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1369 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1370
1371 cur_len = pPrivData->used_len;
1372 if (pPrivData->total_len > pPrivData->used_len)
1373 {
1374 rem_len = pPrivData->total_len - pPrivData->used_len;
1375 }
1376 else
1377 {
1378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1379 "%s: Invalid user data buffer total_len %d used_len %d",
1380 __func__, pPrivData->total_len, pPrivData->used_len);
1381 return -EFAULT;
1382 }
1383
1384 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1385 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1386 cur_len, rem_len);
1387 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1388
1389 /*enough scan result available in cache to return to user space or
1390 scan result needs to be fetched 1st from fw and then return*/
1391 if (len < rem_len)
1392 {
1393 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1394 halStatus = sme_TriggerBatchScanResultInd(
1395 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1396 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1397 pAdapter);
1398 if ( eHAL_STATUS_SUCCESS == halStatus )
1399 {
1400 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1401 {
1402 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1403 rc = wait_for_completion_timeout(
1404 &pAdapter->hdd_get_batch_scan_req_var,
1405 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1406 if (0 == rc)
1407 {
1408 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1409 "%s: Timeout waiting to fetch batch scan rsp from fw",
1410 __func__);
1411 return -EFAULT;
1412 }
1413 }
1414
1415 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
1416 "scancount=%ld\n", pAdapter->numScanList);
1417 pDest += len;
1418 cur_len += len;
1419
1420 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1421 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1422 cur_len, rem_len);
1423 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1424
1425 count = 0;
1426 len = (len - pPrivData->used_len);
1427 pDest = (command + pPrivData->used_len);
1428 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1429 "BATCH SCAN RESULT:");
1430 while(count < len)
1431 {
1432 printk("%c", *(pDest + count));
1433 count++;
1434 }
1435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1436 "%s: copy %d data to user buffer", __func__, len);
1437 if (copy_to_user(pPrivData->buf, pDest, len))
1438 {
1439 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1440 "%s: failed to copy data to user buffer", __func__);
1441 return -EFAULT;
1442 }
1443 }
1444 else
1445 {
1446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1447 "sme_GetBatchScanScan returned failure halStatus %d",
1448 halStatus);
1449 return -EINVAL;
1450 }
1451 }
1452 else
1453 {
1454 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1455 "%s: copy %d data to user buffer", __func__, len);
1456 count = 0;
1457 len = (len - pPrivData->used_len);
1458 pDest = (command + pPrivData->used_len);
1459 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1460 "BATCH SCAN RESULT:");
1461 while(count < len)
1462 {
1463 printk("%c", *(pDest + count));
1464 count++;
1465 }
1466 if (copy_to_user(pPrivData->buf, pDest, len))
1467 {
1468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1469 "%s: failed to copy data to user buffer", __func__);
1470 return -EFAULT;
1471 }
1472 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1473 halStatus = sme_TriggerBatchScanResultInd(
1474 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1475 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1476 pAdapter);
1477 if ( eHAL_STATUS_SUCCESS != halStatus )
1478 {
1479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1480 "sme_GetBatchScanScan returned failure halStatus %d",
1481 halStatus);
1482 }
1483 }
1484
1485 return 0;
1486} /*End of hdd_return_batch_scan_rsp_to_user*/
1487
1488#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1489
Jeff Johnson295189b2012-06-20 16:38:30 -07001490int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1491{
1492 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1493 hdd_priv_data_t priv_data;
1494 tANI_U8 *command = NULL;
1495 int ret = 0;
1496
1497 if (NULL == pAdapter)
1498 {
1499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001500 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001501 ret = -ENODEV;
1502 goto exit;
1503 }
1504
Jeff Johnsone7245742012-09-05 17:12:55 -07001505 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001506 {
1507 ret = -EINVAL;
1508 goto exit;
1509 }
1510
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001511 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1512 {
1513 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1514 "%s:LOGP in Progress. Ignore!!!", __func__);
1515 ret = -EBUSY;
1516 goto exit;
1517 }
1518
Jeff Johnson295189b2012-06-20 16:38:30 -07001519 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1520 {
1521 ret = -EFAULT;
1522 goto exit;
1523 }
1524
1525 command = kmalloc(priv_data.total_len, GFP_KERNEL);
1526 if (!command)
1527 {
1528 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001529 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001530 ret = -ENOMEM;
1531 goto exit;
1532 }
1533
1534 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1535 {
1536 ret = -EFAULT;
1537 goto exit;
1538 }
1539
1540 if ((SIOCDEVPRIVATE + 1) == cmd)
1541 {
1542 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1543
1544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001545 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001546
1547 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1548 {
1549 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1550 sizeof(tSirMacAddr)))
1551 {
1552 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001553 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001554 ret = -EFAULT;
1555 }
1556 }
Amar Singhal0974e402013-02-12 14:27:46 -08001557 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001558 {
Amar Singhal0974e402013-02-12 14:27:46 -08001559 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001560 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001561
Jeff Johnson295189b2012-06-20 16:38:30 -07001562 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001563
1564 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001565 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001566 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001567 "%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 -07001568 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001569 ret = hdd_setBand_helper(dev, ptr);
1570 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001571 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1572 {
1573 char *country_code;
1574
1575 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001576
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001577 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001578 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301579 hdd_checkandupdate_phymode(pAdapter, country_code);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001580 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1581 (void *)(tSmeChangeCountryCallback)
1582 wlan_hdd_change_country_code_callback,
1583 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1584 if (eHAL_STATUS_SUCCESS == ret)
1585 {
1586 ret = wait_for_completion_interruptible_timeout(
1587 &pAdapter->change_country_code,
1588 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1589 if (0 >= ret)
1590 {
1591 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1592 __func__);
1593 }
1594 }
1595 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001596 {
1597 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001598 "%s: SME Change Country code fail ret=%d", __func__, ret);
1599 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001600 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001601
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001602 }
1603 /*
1604 command should be a string having format
1605 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1606 */
Amar Singhal0974e402013-02-12 14:27:46 -08001607 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001608 {
Amar Singhal0974e402013-02-12 14:27:46 -08001609 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001610
1611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001612 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001613
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001614 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001615 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001616 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1617 {
1618 int suspend = 0;
1619 tANI_U8 *ptr = (tANI_U8*)command + 15;
1620
1621 suspend = *ptr - '0';
1622 hdd_set_wlan_suspend_mode(suspend);
1623 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001624#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1625 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1626 {
1627 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001628 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001629 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1630 eHalStatus status = eHAL_STATUS_SUCCESS;
1631
1632 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1633 value = value + 15;
1634
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001635 /* Convert the value from ascii to integer */
1636 ret = kstrtos8(value, 10, &rssi);
1637 if (ret < 0)
1638 {
1639 /* If the input value is greater than max value of datatype, then also
1640 kstrtou8 fails */
1641 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1642 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
1643 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1644 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1645 ret = -EINVAL;
1646 goto exit;
1647 }
1648
Srinivas Girigowdade697412013-02-14 16:31:48 -08001649 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001650
Srinivas Girigowdade697412013-02-14 16:31:48 -08001651 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1652 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1653 {
1654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1655 "Neighbor lookup threshold value %d is out of range"
1656 " (Min: %d Max: %d)", lookUpThreshold,
1657 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1658 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1659 ret = -EINVAL;
1660 goto exit;
1661 }
1662
1663 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1664 "%s: Received Command to Set Roam trigger"
1665 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1666
1667 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1668 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1669 if (eHAL_STATUS_SUCCESS != status)
1670 {
1671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1672 "%s: Failed to set roam trigger, try again", __func__);
1673 ret = -EPERM;
1674 goto exit;
1675 }
1676
1677 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1678 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1679 }
1680 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1681 {
1682 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1683 int rssi = (-1) * lookUpThreshold;
1684 char extra[32];
1685 tANI_U8 len = 0;
1686
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001687 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001688 if (copy_to_user(priv_data.buf, &extra, len + 1))
1689 {
1690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1691 "%s: failed to copy data to user buffer", __func__);
1692 ret = -EFAULT;
1693 goto exit;
1694 }
1695 }
1696 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1697 {
1698 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001699 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001700 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001701
Srinivas Girigowdade697412013-02-14 16:31:48 -08001702 /* input refresh period is in terms of seconds */
1703 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1704 value = value + 18;
1705 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001706 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001707 if (ret < 0)
1708 {
1709 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001710 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001712 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001713 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001714 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1715 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001716 ret = -EINVAL;
1717 goto exit;
1718 }
1719
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001720 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1721 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001722 {
1723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001724 "Roam scan period value %d is out of range"
1725 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001726 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1727 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001728 ret = -EINVAL;
1729 goto exit;
1730 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001731 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001732
1733 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1734 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001735 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001736
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001737 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1738 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001739 }
1740 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1741 {
1742 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1743 char extra[32];
1744 tANI_U8 len = 0;
1745
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001746 len = scnprintf(extra, sizeof(extra), "%s %d",
1747 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001748 /* Returned value is in units of seconds */
1749 if (copy_to_user(priv_data.buf, &extra, len + 1))
1750 {
1751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1752 "%s: failed to copy data to user buffer", __func__);
1753 ret = -EFAULT;
1754 goto exit;
1755 }
1756 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001757 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1758 {
1759 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001760 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001761 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001762
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001763 /* input refresh period is in terms of seconds */
1764 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1765 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001766
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001767 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001768 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001769 if (ret < 0)
1770 {
1771 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001772 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001773 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001774 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001775 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001776 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1777 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1778 ret = -EINVAL;
1779 goto exit;
1780 }
1781
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001782 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1783 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1784 {
1785 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1786 "Neighbor scan results refresh period value %d is out of range"
1787 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1788 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1789 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1790 ret = -EINVAL;
1791 goto exit;
1792 }
1793 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1794
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001795 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1796 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001797 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001798
1799 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1800 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1801 }
1802 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1803 {
1804 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1805 char extra[32];
1806 tANI_U8 len = 0;
1807
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001808 len = scnprintf(extra, sizeof(extra), "%s %d",
1809 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001810 /* Returned value is in units of seconds */
1811 if (copy_to_user(priv_data.buf, &extra, len + 1))
1812 {
1813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1814 "%s: failed to copy data to user buffer", __func__);
1815 ret = -EFAULT;
1816 goto exit;
1817 }
1818 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001819#ifdef FEATURE_WLAN_LFR
1820 /* SETROAMMODE */
1821 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1822 {
1823 tANI_U8 *value = command;
1824 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1825
1826 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1827 value = value + SIZE_OF_SETROAMMODE + 1;
1828
1829 /* Convert the value from ascii to integer */
1830 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1831 if (ret < 0)
1832 {
1833 /* If the input value is greater than max value of datatype, then also
1834 kstrtou8 fails */
1835 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1836 "%s: kstrtou8 failed range [%d - %d]", __func__,
1837 CFG_LFR_FEATURE_ENABLED_MIN,
1838 CFG_LFR_FEATURE_ENABLED_MAX);
1839 ret = -EINVAL;
1840 goto exit;
1841 }
1842 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1843 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1844 {
1845 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1846 "Roam Mode value %d is out of range"
1847 " (Min: %d Max: %d)", roamMode,
1848 CFG_LFR_FEATURE_ENABLED_MIN,
1849 CFG_LFR_FEATURE_ENABLED_MAX);
1850 ret = -EINVAL;
1851 goto exit;
1852 }
1853
1854 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1855 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
1856 /*
1857 * Note that
1858 * SETROAMMODE 0 is to enable LFR while
1859 * SETROAMMODE 1 is to disable LFR, but
1860 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
1861 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
1862 */
1863 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1864 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
1865 else
1866 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
1867
1868 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
1869 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
1870 }
1871 /* GETROAMMODE */
1872 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
1873 {
1874 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1875 char extra[32];
1876 tANI_U8 len = 0;
1877
1878 /*
1879 * roamMode value shall be inverted because the sementics is different.
1880 */
1881 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1882 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
1883 else
1884 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
1885
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001886 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001887 if (copy_to_user(priv_data.buf, &extra, len + 1))
1888 {
1889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1890 "%s: failed to copy data to user buffer", __func__);
1891 ret = -EFAULT;
1892 goto exit;
1893 }
1894 }
1895#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08001896#endif
1897#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1898 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1899 {
1900 tANI_U8 *value = command;
1901 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1902
1903 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1904 value = value + 13;
1905 /* Convert the value from ascii to integer */
1906 ret = kstrtou8(value, 10, &roamRssiDiff);
1907 if (ret < 0)
1908 {
1909 /* If the input value is greater than max value of datatype, then also
1910 kstrtou8 fails */
1911 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1912 "%s: kstrtou8 failed range [%d - %d]", __func__,
1913 CFG_ROAM_RSSI_DIFF_MIN,
1914 CFG_ROAM_RSSI_DIFF_MAX);
1915 ret = -EINVAL;
1916 goto exit;
1917 }
1918
1919 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1920 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1921 {
1922 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1923 "Roam rssi diff value %d is out of range"
1924 " (Min: %d Max: %d)", roamRssiDiff,
1925 CFG_ROAM_RSSI_DIFF_MIN,
1926 CFG_ROAM_RSSI_DIFF_MAX);
1927 ret = -EINVAL;
1928 goto exit;
1929 }
1930
1931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1932 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1933
1934 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1935 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1936 }
1937 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1938 {
1939 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1940 char extra[32];
1941 tANI_U8 len = 0;
1942
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001943 len = scnprintf(extra, sizeof(extra), "%s %d",
1944 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001945 if (copy_to_user(priv_data.buf, &extra, len + 1))
1946 {
1947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1948 "%s: failed to copy data to user buffer", __func__);
1949 ret = -EFAULT;
1950 goto exit;
1951 }
1952 }
1953#endif
1954#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1955 else if (strncmp(command, "GETBAND", 7) == 0)
1956 {
1957 int band = -1;
1958 char extra[32];
1959 tANI_U8 len = 0;
1960 hdd_getBand_helper(pHddCtx, &band);
1961
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001962 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001963 if (copy_to_user(priv_data.buf, &extra, len + 1))
1964 {
1965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1966 "%s: failed to copy data to user buffer", __func__);
1967 ret = -EFAULT;
1968 goto exit;
1969 }
1970 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001971 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1972 {
1973 tANI_U8 *value = command;
1974 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1975 tANI_U8 numChannels = 0;
1976 eHalStatus status = eHAL_STATUS_SUCCESS;
1977
1978 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1979 if (eHAL_STATUS_SUCCESS != status)
1980 {
1981 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1982 "%s: Failed to parse channel list information", __func__);
1983 ret = -EINVAL;
1984 goto exit;
1985 }
1986
1987 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
1988 {
1989 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1990 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
1991 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
1992 ret = -EINVAL;
1993 goto exit;
1994 }
1995 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
1996 numChannels);
1997 if (eHAL_STATUS_SUCCESS != status)
1998 {
1999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2000 "%s: Failed to update channel list information", __func__);
2001 ret = -EINVAL;
2002 goto exit;
2003 }
2004 }
2005 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2006 {
2007 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2008 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002009 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002010 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002011 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002012
2013 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2014 ChannelList, &numChannels ))
2015 {
2016 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2017 "%s: failed to get roam scan channel list", __func__);
2018 ret = -EFAULT;
2019 goto exit;
2020 }
2021 /* output channel list is of the format
2022 [Number of roam scan channels][Channel1][Channel2]... */
2023 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002024 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002025 for (j = 0; (j < numChannels); j++)
2026 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002027 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2028 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002029 }
2030
2031 if (copy_to_user(priv_data.buf, &extra, len + 1))
2032 {
2033 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2034 "%s: failed to copy data to user buffer", __func__);
2035 ret = -EFAULT;
2036 goto exit;
2037 }
2038 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002039 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2040 {
2041 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2042 char extra[32];
2043 tANI_U8 len = 0;
2044
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002045 /* Check if the features OKC/CCX/11R are supported simultaneously,
2046 then this operation is not permitted (return FAILURE) */
2047 if (ccxMode &&
2048 hdd_is_okc_mode_enabled(pHddCtx) &&
2049 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2050 {
2051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2052 "%s: OKC/CCX/11R are supported simultaneously"
2053 " hence this operation is not permitted!", __func__);
2054 ret = -EPERM;
2055 goto exit;
2056 }
2057
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002058 len = scnprintf(extra, sizeof(extra), "%s %d",
2059 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002060 if (copy_to_user(priv_data.buf, &extra, len + 1))
2061 {
2062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2063 "%s: failed to copy data to user buffer", __func__);
2064 ret = -EFAULT;
2065 goto exit;
2066 }
2067 }
2068 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2069 {
2070 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2071 char extra[32];
2072 tANI_U8 len = 0;
2073
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002074 /* Check if the features OKC/CCX/11R are supported simultaneously,
2075 then this operation is not permitted (return FAILURE) */
2076 if (okcMode &&
2077 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2078 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2079 {
2080 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2081 "%s: OKC/CCX/11R are supported simultaneously"
2082 " hence this operation is not permitted!", __func__);
2083 ret = -EPERM;
2084 goto exit;
2085 }
2086
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002087 len = scnprintf(extra, sizeof(extra), "%s %d",
2088 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002089 if (copy_to_user(priv_data.buf, &extra, len + 1))
2090 {
2091 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2092 "%s: failed to copy data to user buffer", __func__);
2093 ret = -EFAULT;
2094 goto exit;
2095 }
2096 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002097 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002098 {
2099 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2100 char extra[32];
2101 tANI_U8 len = 0;
2102
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002103 len = scnprintf(extra, sizeof(extra), "%s %d",
2104 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002105 if (copy_to_user(priv_data.buf, &extra, len + 1))
2106 {
2107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2108 "%s: failed to copy data to user buffer", __func__);
2109 ret = -EFAULT;
2110 goto exit;
2111 }
2112 }
2113 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2114 {
2115 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2116 char extra[32];
2117 tANI_U8 len = 0;
2118
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002119 len = scnprintf(extra, sizeof(extra), "%s %d",
2120 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002121 if (copy_to_user(priv_data.buf, &extra, len + 1))
2122 {
2123 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2124 "%s: failed to copy data to user buffer", __func__);
2125 ret = -EFAULT;
2126 goto exit;
2127 }
2128 }
2129 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2130 {
2131 tANI_U8 *value = command;
2132 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2133
2134 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2135 value = value + 26;
2136 /* Convert the value from ascii to integer */
2137 ret = kstrtou8(value, 10, &minTime);
2138 if (ret < 0)
2139 {
2140 /* If the input value is greater than max value of datatype, then also
2141 kstrtou8 fails */
2142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2143 "%s: kstrtou8 failed range [%d - %d]", __func__,
2144 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2145 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2146 ret = -EINVAL;
2147 goto exit;
2148 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002149 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2150 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2151 {
2152 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2153 "scan min channel time value %d is out of range"
2154 " (Min: %d Max: %d)", minTime,
2155 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2156 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2157 ret = -EINVAL;
2158 goto exit;
2159 }
2160
2161 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2162 "%s: Received Command to change channel min time = %d", __func__, minTime);
2163
2164 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2165 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2166 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002167 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2168 {
2169 tANI_U8 *value = command;
2170 tANI_U8 channel = 0;
2171 tANI_U8 dwellTime = 0;
2172 tANI_U8 bufLen = 0;
2173 tANI_U8 *buf = NULL;
2174 tSirMacAddr targetApBssid;
2175 eHalStatus status = eHAL_STATUS_SUCCESS;
2176 struct ieee80211_channel chan;
2177 tANI_U8 finalLen = 0;
2178 tANI_U8 *finalBuf = NULL;
2179 tANI_U8 temp = 0;
2180 u64 cookie;
2181 hdd_station_ctx_t *pHddStaCtx = NULL;
2182 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2183
2184 /* if not associated, no need to send action frame */
2185 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2186 {
2187 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2188 ret = -EINVAL;
2189 goto exit;
2190 }
2191
2192 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2193 &dwellTime, &buf, &bufLen);
2194 if (eHAL_STATUS_SUCCESS != status)
2195 {
2196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2197 "%s: Failed to parse send action frame data", __func__);
2198 ret = -EINVAL;
2199 goto exit;
2200 }
2201
2202 /* if the target bssid is different from currently associated AP,
2203 then no need to send action frame */
2204 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2205 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2206 {
2207 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2208 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002209 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002210 goto exit;
2211 }
2212
2213 /* if the channel number is different from operating channel then
2214 no need to send action frame */
2215 if (channel != pHddStaCtx->conn_info.operationChannel)
2216 {
2217 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2218 "%s: channel(%d) is different from operating channel(%d)",
2219 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2220 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002221 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002222 goto exit;
2223 }
2224 chan.center_freq = sme_ChnToFreq(channel);
2225
2226 finalLen = bufLen + 24;
2227 finalBuf = vos_mem_malloc(finalLen);
2228 if (NULL == finalBuf)
2229 {
2230 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2231 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002232 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002233 goto exit;
2234 }
2235 vos_mem_zero(finalBuf, finalLen);
2236
2237 /* Fill subtype */
2238 temp = SIR_MAC_MGMT_ACTION << 4;
2239 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2240
2241 /* Fill type */
2242 temp = SIR_MAC_MGMT_FRAME;
2243 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2244
2245 /* Fill destination address (bssid of the AP) */
2246 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2247
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002248 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002249 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2250
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002251 /* Fill BSSID (AP mac address) */
2252 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002253
2254 /* Fill received buffer from 24th address */
2255 vos_mem_copy(finalBuf + 24, buf, bufLen);
2256
Jeff Johnson11c33152013-04-16 17:52:40 -07002257 /* done with the parsed buffer */
2258 vos_mem_free(buf);
2259
Yue Maf49ba872013-08-19 12:04:25 -07002260 wlan_hdd_action( NULL,
2261#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2262 &(pAdapter->wdev),
2263#else
2264 dev,
2265#endif
2266 &chan, 0,
2267#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2268 NL80211_CHAN_HT20, 1,
2269#endif
2270 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002271 1, &cookie );
2272 vos_mem_free(finalBuf);
2273 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002274 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2275 {
2276 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2277 char extra[32];
2278 tANI_U8 len = 0;
2279
2280 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002281 len = scnprintf(extra, sizeof(extra), "%s %d",
2282 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002283 if (copy_to_user(priv_data.buf, &extra, len + 1))
2284 {
2285 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2286 "%s: failed to copy data to user buffer", __func__);
2287 ret = -EFAULT;
2288 goto exit;
2289 }
2290 }
2291 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2292 {
2293 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002294 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002295 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002296
2297 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2298 value = value + 19;
2299 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002300 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002301 if (ret < 0)
2302 {
2303 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002304 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002305 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002306 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002307 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2308 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2309 ret = -EINVAL;
2310 goto exit;
2311 }
2312
2313 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2314 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2315 {
2316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2317 "lfr mode value %d is out of range"
2318 " (Min: %d Max: %d)", maxTime,
2319 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2320 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2321 ret = -EINVAL;
2322 goto exit;
2323 }
2324
2325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2326 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2327
2328 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002329
2330 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2331 * where RFS is the RF Switching time. It is twice RFS to consider the
2332 * time to go off channel and return to the home channel. */
2333 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2334 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2335 {
2336 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2337 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
2338 " Hence enforcing home away time to disable (0)",
2339 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2340 homeAwayTime = 0;
2341 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2342 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2343 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002344 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2345 }
2346 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2347 {
2348 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2349 char extra[32];
2350 tANI_U8 len = 0;
2351
2352 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002353 len = scnprintf(extra, sizeof(extra), "%s %d",
2354 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002355 if (copy_to_user(priv_data.buf, &extra, len + 1))
2356 {
2357 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2358 "%s: failed to copy data to user buffer", __func__);
2359 ret = -EFAULT;
2360 goto exit;
2361 }
2362 }
2363 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2364 {
2365 tANI_U8 *value = command;
2366 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2367
2368 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2369 value = value + 16;
2370 /* Convert the value from ascii to integer */
2371 ret = kstrtou16(value, 10, &val);
2372 if (ret < 0)
2373 {
2374 /* If the input value is greater than max value of datatype, then also
2375 kstrtou16 fails */
2376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2377 "%s: kstrtou16 failed range [%d - %d]", __func__,
2378 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2379 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2380 ret = -EINVAL;
2381 goto exit;
2382 }
2383
2384 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2385 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2386 {
2387 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2388 "scan home time value %d is out of range"
2389 " (Min: %d Max: %d)", val,
2390 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2391 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2392 ret = -EINVAL;
2393 goto exit;
2394 }
2395
2396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2397 "%s: Received Command to change scan home time = %d", __func__, val);
2398
2399 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2400 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2401 }
2402 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2403 {
2404 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2405 char extra[32];
2406 tANI_U8 len = 0;
2407
2408 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002409 len = scnprintf(extra, sizeof(extra), "%s %d",
2410 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002411 if (copy_to_user(priv_data.buf, &extra, len + 1))
2412 {
2413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2414 "%s: failed to copy data to user buffer", __func__);
2415 ret = -EFAULT;
2416 goto exit;
2417 }
2418 }
2419 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2420 {
2421 tANI_U8 *value = command;
2422 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2423
2424 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2425 value = value + 17;
2426 /* Convert the value from ascii to integer */
2427 ret = kstrtou8(value, 10, &val);
2428 if (ret < 0)
2429 {
2430 /* If the input value is greater than max value of datatype, then also
2431 kstrtou8 fails */
2432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2433 "%s: kstrtou8 failed range [%d - %d]", __func__,
2434 CFG_ROAM_INTRA_BAND_MIN,
2435 CFG_ROAM_INTRA_BAND_MAX);
2436 ret = -EINVAL;
2437 goto exit;
2438 }
2439
2440 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2441 (val > CFG_ROAM_INTRA_BAND_MAX))
2442 {
2443 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2444 "intra band mode value %d is out of range"
2445 " (Min: %d Max: %d)", val,
2446 CFG_ROAM_INTRA_BAND_MIN,
2447 CFG_ROAM_INTRA_BAND_MAX);
2448 ret = -EINVAL;
2449 goto exit;
2450 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2452 "%s: Received Command to change intra band = %d", __func__, val);
2453
2454 pHddCtx->cfg_ini->nRoamIntraBand = val;
2455 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2456 }
2457 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2458 {
2459 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2460 char extra[32];
2461 tANI_U8 len = 0;
2462
2463 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002464 len = scnprintf(extra, sizeof(extra), "%s %d",
2465 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002466 if (copy_to_user(priv_data.buf, &extra, len + 1))
2467 {
2468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2469 "%s: failed to copy data to user buffer", __func__);
2470 ret = -EFAULT;
2471 goto exit;
2472 }
2473 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002474 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2475 {
2476 tANI_U8 *value = command;
2477 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2478
2479 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2480 value = value + 15;
2481 /* Convert the value from ascii to integer */
2482 ret = kstrtou8(value, 10, &nProbes);
2483 if (ret < 0)
2484 {
2485 /* If the input value is greater than max value of datatype, then also
2486 kstrtou8 fails */
2487 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2488 "%s: kstrtou8 failed range [%d - %d]", __func__,
2489 CFG_ROAM_SCAN_N_PROBES_MIN,
2490 CFG_ROAM_SCAN_N_PROBES_MAX);
2491 ret = -EINVAL;
2492 goto exit;
2493 }
2494
2495 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2496 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2497 {
2498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2499 "NProbes value %d is out of range"
2500 " (Min: %d Max: %d)", nProbes,
2501 CFG_ROAM_SCAN_N_PROBES_MIN,
2502 CFG_ROAM_SCAN_N_PROBES_MAX);
2503 ret = -EINVAL;
2504 goto exit;
2505 }
2506
2507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2508 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2509
2510 pHddCtx->cfg_ini->nProbes = nProbes;
2511 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2512 }
2513 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2514 {
2515 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2516 char extra[32];
2517 tANI_U8 len = 0;
2518
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002519 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002520 if (copy_to_user(priv_data.buf, &extra, len + 1))
2521 {
2522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2523 "%s: failed to copy data to user buffer", __func__);
2524 ret = -EFAULT;
2525 goto exit;
2526 }
2527 }
2528 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2529 {
2530 tANI_U8 *value = command;
2531 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002532 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002533
2534 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2535 /* input value is in units of msec */
2536 value = value + 20;
2537 /* Convert the value from ascii to integer */
2538 ret = kstrtou16(value, 10, &homeAwayTime);
2539 if (ret < 0)
2540 {
2541 /* If the input value is greater than max value of datatype, then also
2542 kstrtou8 fails */
2543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2544 "%s: kstrtou8 failed range [%d - %d]", __func__,
2545 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2546 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2547 ret = -EINVAL;
2548 goto exit;
2549 }
2550
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002551 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2552 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2553 {
2554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2555 "homeAwayTime value %d is out of range"
2556 " (Min: %d Max: %d)", homeAwayTime,
2557 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2558 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2559 ret = -EINVAL;
2560 goto exit;
2561 }
2562
2563 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2564 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2565
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002566 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2567 * where RFS is the RF Switching time. It is twice RFS to consider the
2568 * time to go off channel and return to the home channel. */
2569 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2570 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2571 {
2572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2573 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
2574 " Hence enforcing home away time to disable (0)",
2575 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2576 homeAwayTime = 0;
2577 }
2578
2579 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2580 {
2581 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2582 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2583 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002584 }
2585 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2586 {
2587 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2588 char extra[32];
2589 tANI_U8 len = 0;
2590
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002591 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002592 if (copy_to_user(priv_data.buf, &extra, len + 1))
2593 {
2594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2595 "%s: failed to copy data to user buffer", __func__);
2596 ret = -EFAULT;
2597 goto exit;
2598 }
2599 }
2600 else if (strncmp(command, "REASSOC", 7) == 0)
2601 {
2602 tANI_U8 *value = command;
2603 tANI_U8 channel = 0;
2604 tSirMacAddr targetApBssid;
2605 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002606#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2607 tCsrHandoffRequest handoffInfo;
2608#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002609 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002610 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2611
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002612 /* if not associated, no need to proceed with reassoc */
2613 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2614 {
2615 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2616 ret = -EINVAL;
2617 goto exit;
2618 }
2619
2620 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2621 if (eHAL_STATUS_SUCCESS != status)
2622 {
2623 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2624 "%s: Failed to parse reassoc command data", __func__);
2625 ret = -EINVAL;
2626 goto exit;
2627 }
2628
2629 /* if the target bssid is same as currently associated AP,
2630 then no need to proceed with reassoc */
2631 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2632 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2633 {
2634 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2635 ret = -EINVAL;
2636 goto exit;
2637 }
2638
2639 /* Check channel number is a valid channel number */
2640 if(VOS_STATUS_SUCCESS !=
2641 wlan_hdd_validate_operation_channel(pAdapter, channel))
2642 {
2643 hddLog(VOS_TRACE_LEVEL_ERROR,
2644 "%s: Invalid Channel [%d] \n", __func__, channel);
2645 return -EINVAL;
2646 }
2647
2648 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002649#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2650 handoffInfo.channel = channel;
2651 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2652 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2653#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002654 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002655#endif
2656#ifdef FEATURE_WLAN_LFR
2657 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2658 {
2659 tANI_U8 *value = command;
2660 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2661
2662 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2663 value = value + 12;
2664 /* Convert the value from ascii to integer */
2665 ret = kstrtou8(value, 10, &lfrMode);
2666 if (ret < 0)
2667 {
2668 /* If the input value is greater than max value of datatype, then also
2669 kstrtou8 fails */
2670 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2671 "%s: kstrtou8 failed range [%d - %d]", __func__,
2672 CFG_LFR_FEATURE_ENABLED_MIN,
2673 CFG_LFR_FEATURE_ENABLED_MAX);
2674 ret = -EINVAL;
2675 goto exit;
2676 }
2677
2678 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2679 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2680 {
2681 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2682 "lfr mode value %d is out of range"
2683 " (Min: %d Max: %d)", lfrMode,
2684 CFG_LFR_FEATURE_ENABLED_MIN,
2685 CFG_LFR_FEATURE_ENABLED_MAX);
2686 ret = -EINVAL;
2687 goto exit;
2688 }
2689
2690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2691 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2692
2693 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2694 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2695 }
2696#endif
2697#ifdef WLAN_FEATURE_VOWIFI_11R
2698 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2699 {
2700 tANI_U8 *value = command;
2701 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2702
2703 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2704 value = value + 18;
2705 /* Convert the value from ascii to integer */
2706 ret = kstrtou8(value, 10, &ft);
2707 if (ret < 0)
2708 {
2709 /* If the input value is greater than max value of datatype, then also
2710 kstrtou8 fails */
2711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2712 "%s: kstrtou8 failed range [%d - %d]", __func__,
2713 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2714 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2715 ret = -EINVAL;
2716 goto exit;
2717 }
2718
2719 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2720 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2721 {
2722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2723 "ft mode value %d is out of range"
2724 " (Min: %d Max: %d)", ft,
2725 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2726 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2727 ret = -EINVAL;
2728 goto exit;
2729 }
2730
2731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2732 "%s: Received Command to change ft mode = %d", __func__, ft);
2733
2734 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2735 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2736 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302737
2738 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2739 {
2740 tANI_U8 *value = command;
2741 tSirMacAddr targetApBssid;
2742 tANI_U8 trigger = 0;
2743 eHalStatus status = eHAL_STATUS_SUCCESS;
2744 hdd_station_ctx_t *pHddStaCtx = NULL;
2745 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2746
2747 /* if not associated, no need to proceed with reassoc */
2748 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2749 {
2750 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2751 ret = -EINVAL;
2752 goto exit;
2753 }
2754
2755 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2756 if (eHAL_STATUS_SUCCESS != status)
2757 {
2758 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2759 "%s: Failed to parse reassoc command data", __func__);
2760 ret = -EINVAL;
2761 goto exit;
2762 }
2763
2764 /* if the target bssid is same as currently associated AP,
2765 then no need to proceed with reassoc */
2766 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2767 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2768 {
2769 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2770 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2771 __func__);
2772 ret = -EINVAL;
2773 goto exit;
2774 }
2775
2776 /* Proceed with scan/roam */
2777 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2778 &targetApBssid[0],
2779 (tSmeFastRoamTrigger)(trigger));
2780 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002781#endif
2782#ifdef FEATURE_WLAN_CCX
2783 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2784 {
2785 tANI_U8 *value = command;
2786 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2787
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002788 /* Check if the features OKC/CCX/11R are supported simultaneously,
2789 then this operation is not permitted (return FAILURE) */
2790 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2791 hdd_is_okc_mode_enabled(pHddCtx) &&
2792 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2793 {
2794 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2795 "%s: OKC/CCX/11R are supported simultaneously"
2796 " hence this operation is not permitted!", __func__);
2797 ret = -EPERM;
2798 goto exit;
2799 }
2800
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002801 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2802 value = value + 11;
2803 /* Convert the value from ascii to integer */
2804 ret = kstrtou8(value, 10, &ccxMode);
2805 if (ret < 0)
2806 {
2807 /* If the input value is greater than max value of datatype, then also
2808 kstrtou8 fails */
2809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2810 "%s: kstrtou8 failed range [%d - %d]", __func__,
2811 CFG_CCX_FEATURE_ENABLED_MIN,
2812 CFG_CCX_FEATURE_ENABLED_MAX);
2813 ret = -EINVAL;
2814 goto exit;
2815 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002816 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2817 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2818 {
2819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2820 "Ccx mode value %d is out of range"
2821 " (Min: %d Max: %d)", ccxMode,
2822 CFG_CCX_FEATURE_ENABLED_MIN,
2823 CFG_CCX_FEATURE_ENABLED_MAX);
2824 ret = -EINVAL;
2825 goto exit;
2826 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2828 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
2829
2830 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
2831 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
2832 }
2833#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002834 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
2835 {
2836 tANI_U8 *value = command;
2837 tANI_BOOLEAN roamScanControl = 0;
2838
2839 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
2840 value = value + 19;
2841 /* Convert the value from ascii to integer */
2842 ret = kstrtou8(value, 10, &roamScanControl);
2843 if (ret < 0)
2844 {
2845 /* If the input value is greater than max value of datatype, then also
2846 kstrtou8 fails */
2847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2848 "%s: kstrtou8 failed ", __func__);
2849 ret = -EINVAL;
2850 goto exit;
2851 }
2852
2853 if (0 != roamScanControl)
2854 {
2855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2856 "roam scan control invalid value = %d",
2857 roamScanControl);
2858 ret = -EINVAL;
2859 goto exit;
2860 }
2861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2862 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
2863
2864 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
2865 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002866#ifdef FEATURE_WLAN_OKC
2867 else if (strncmp(command, "SETOKCMODE", 10) == 0)
2868 {
2869 tANI_U8 *value = command;
2870 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
2871
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002872 /* Check if the features OKC/CCX/11R are supported simultaneously,
2873 then this operation is not permitted (return FAILURE) */
2874 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2875 hdd_is_okc_mode_enabled(pHddCtx) &&
2876 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2877 {
2878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2879 "%s: OKC/CCX/11R are supported simultaneously"
2880 " hence this operation is not permitted!", __func__);
2881 ret = -EPERM;
2882 goto exit;
2883 }
2884
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002885 /* Move pointer to ahead of SETOKCMODE<delimiter> */
2886 value = value + 11;
2887 /* Convert the value from ascii to integer */
2888 ret = kstrtou8(value, 10, &okcMode);
2889 if (ret < 0)
2890 {
2891 /* If the input value is greater than max value of datatype, then also
2892 kstrtou8 fails */
2893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2894 "%s: kstrtou8 failed range [%d - %d]", __func__,
2895 CFG_OKC_FEATURE_ENABLED_MIN,
2896 CFG_OKC_FEATURE_ENABLED_MAX);
2897 ret = -EINVAL;
2898 goto exit;
2899 }
2900
2901 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
2902 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
2903 {
2904 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2905 "Okc mode value %d is out of range"
2906 " (Min: %d Max: %d)", okcMode,
2907 CFG_OKC_FEATURE_ENABLED_MIN,
2908 CFG_OKC_FEATURE_ENABLED_MAX);
2909 ret = -EINVAL;
2910 goto exit;
2911 }
2912
2913 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2914 "%s: Received Command to change okc mode = %d", __func__, okcMode);
2915
2916 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
2917 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002918 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
2919 {
2920 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
2921 char extra[32];
2922 tANI_U8 len = 0;
2923
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002924 len = scnprintf(extra, sizeof(extra), "%s %d",
2925 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002926 if (copy_to_user(priv_data.buf, &extra, len + 1))
2927 {
2928 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2929 "%s: failed to copy data to user buffer", __func__);
2930 ret = -EFAULT;
2931 goto exit;
2932 }
2933 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002934#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302935#ifdef WLAN_FEATURE_PACKET_FILTERING
2936 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2937 {
2938 tANI_U8 filterType = 0;
2939 tANI_U8 *value = command;
2940
2941 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2942 value = value + 22;
2943
2944 /* Convert the value from ascii to integer */
2945 ret = kstrtou8(value, 10, &filterType);
2946 if (ret < 0)
2947 {
2948 /* If the input value is greater than max value of datatype,
2949 * then also kstrtou8 fails
2950 */
2951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2952 "%s: kstrtou8 failed range ", __func__);
2953 ret = -EINVAL;
2954 goto exit;
2955 }
2956
2957 if (filterType != 0 && filterType != 1)
2958 {
2959 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2960 "%s: Accepted Values are 0 and 1 ", __func__);
2961 ret = -EINVAL;
2962 goto exit;
2963 }
2964 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2965 pAdapter->sessionId);
2966 }
2967#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302968 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2969 {
2970 char *dhcpPhase;
2971 dhcpPhase = command + 12;
2972 if ('1' == *dhcpPhase)
2973 {
2974 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2975 pAdapter->macAddressCurrent.bytes);
2976 }
2977 else if ('2' == *dhcpPhase)
2978 {
2979 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
2980 pAdapter->macAddressCurrent.bytes);
2981 }
2982 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07002983 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
2984 {
2985 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
2986 }
2987 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
2988 {
2989 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
2990 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05302991 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
2992 {
2993 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
2994 char extra[32];
2995 tANI_U8 len = 0;
2996
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002997 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05302998 (int)pCfg->nActiveMaxChnTime);
2999 if (copy_to_user(priv_data.buf, &extra, len + 1))
3000 {
3001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3002 "%s: failed to copy data to user buffer", __func__);
3003 ret = -EFAULT;
3004 goto exit;
3005 }
3006 ret = len;
3007 }
3008 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3009 {
3010 tANI_U8 *value = command;
3011 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3012 int val = 0, temp;
3013
3014 value = value + 13;
3015 temp = kstrtou32(value, 10, &val);
3016 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3017 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3018 {
3019 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3020 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3021 ret = -EFAULT;
3022 goto exit;
3023 }
3024 pCfg->nActiveMaxChnTime = val;
3025 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003026 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3027 {
3028 tANI_U8 filterType = 0;
3029 tANI_U8 *value;
3030 value = command + 9;
3031
3032 /* Convert the value from ascii to integer */
3033 ret = kstrtou8(value, 10, &filterType);
3034 if (ret < 0)
3035 {
3036 /* If the input value is greater than max value of datatype,
3037 * then also kstrtou8 fails
3038 */
3039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3040 "%s: kstrtou8 failed range ", __func__);
3041 ret = -EINVAL;
3042 goto exit;
3043 }
3044 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3045 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3046 {
3047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3048 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3049 " 2-Sink ", __func__);
3050 ret = -EINVAL;
3051 goto exit;
3052 }
3053 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3054 pHddCtx->drvr_miracast = filterType;
3055 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3056 }
Leo Chang614d2072013-08-22 14:59:44 -07003057 else if (strncmp(command, "SETMCRATE", 9) == 0)
3058 {
3059 int rc;
3060 tANI_U8 *value = command;
3061 int targetRate;
3062
3063 /* Only valid for SAP mode */
3064 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3065 {
3066 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3067 "%s: SAP mode is not running", __func__);
3068 ret = -EFAULT;
3069 goto exit;
3070 }
3071
3072 /* Move pointer to ahead of SETMCRATE<delimiter> */
3073 /* input value is in units of hundred kbps */
3074 value = value + 10;
3075 /* Convert the value from ascii to integer, decimal base */
3076 ret = kstrtouint(value, 10, &targetRate);
3077
3078 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
3079 if (rc)
3080 {
3081 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3082 "%s: Set MC Rate Fail %d", __func__, rc);
3083 ret = -EFAULT;
3084 goto exit;
3085 }
3086 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303087#ifdef FEATURE_WLAN_BATCH_SCAN
3088 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3089 {
3090 char extra[32];
3091 tANI_U8 len = 0;
3092 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3093
3094 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3095 {
3096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3097 "%s: Batch scan feature is not supported by FW", __func__);
3098 ret = -EINVAL;
3099 goto exit;
3100 }
3101
3102 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3103 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3104 {
3105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3106 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3107 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3108 " mode",
3109 pAdapter->device_mode);
3110 ret = -EINVAL;
3111 goto exit;
3112 }
3113
3114 len = snprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
3115 version);
3116 if (copy_to_user(priv_data.buf, &extra, len + 1))
3117 {
3118 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3119 "%s: failed to copy data to user buffer", __func__);
3120 ret = -EFAULT;
3121 goto exit;
3122 }
3123 ret = HDD_BATCH_SCAN_VERSION;
3124 }
3125 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3126 {
3127 int status;
3128 tANI_U8 *value = (command + 16);
3129 eHalStatus halStatus;
3130 unsigned long rc;
3131 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3132 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3133
3134 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3135 {
3136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3137 "%s: Batch scan feature is not supported by FW", __func__);
3138 ret = -EINVAL;
3139 goto exit;
3140 }
3141
3142 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3143 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3144 {
3145 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3146 "Received WLS_BATCHING_SET command in invalid mode %d "
3147 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3148 pAdapter->device_mode);
3149 ret = -EINVAL;
3150 goto exit;
3151 }
3152
3153 status = hdd_parse_set_batchscan_command(value, pReq);
3154 if (status)
3155 {
3156 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3157 "Invalid WLS_BATCHING_SET command");
3158 ret = -EINVAL;
3159 goto exit;
3160 }
3161 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3162 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3163 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3164 pAdapter);
3165
3166 if ( eHAL_STATUS_SUCCESS == halStatus )
3167 {
3168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3169 "sme_SetBatchScanReq returned success halStatus %d",
3170 halStatus);
3171 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3172 {
3173 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3174 rc = wait_for_completion_timeout(
3175 &pAdapter->hdd_set_batch_scan_req_var,
3176 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3177 if (0 == rc)
3178 {
3179 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3180 "%s: Timeout waiting for set batch scan to complete",
3181 __func__);
3182 ret = -EINVAL;
3183 goto exit;
3184 }
3185 }
3186 if ( !pRsp->nScansToBatch )
3187 {
3188 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3189 "%s: Received set batch scan failure response from FW",
3190 __func__, pRsp->nScansToBatch);
3191 ret = -EINVAL;
3192 goto exit;
3193 }
3194 /*As per the Batch Scan Framework API we should return the MIN of
3195 either MSCAN or the max # of scans firmware can cache*/
3196 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3197
3198 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3199 "%s: request MSCAN %d response MSCAN %d ret %d",
3200 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3201 }
3202 else
3203 {
3204 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3205 "sme_SetBatchScanReq returned failure halStatus %d",
3206 halStatus);
3207 ret = -EINVAL;
3208 goto exit;
3209 }
3210 }
3211 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3212 {
3213 eHalStatus halStatus;
3214 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3215 pInd->param = 0;
3216
3217 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3218 {
3219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3220 "%s: Batch scan feature is not supported by FW", __func__);
3221 ret = -EINVAL;
3222 goto exit;
3223 }
3224
3225 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3226 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3227 {
3228 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3229 "Received WLS_BATCHING_STOP command in invalid mode %d "
3230 "WLS_BATCHING_STOP is only allowed in infra STA/P2P client"
3231 " mode",
3232 pAdapter->device_mode);
3233 ret = -EINVAL;
3234 goto exit;
3235 }
3236
3237 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3238 pAdapter->sessionId);
3239 if ( eHAL_STATUS_SUCCESS == halStatus )
3240 {
3241 ret = 0;
3242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3243 "sme_StopBatchScanInd returned success halStatus %d",
3244 halStatus);
3245 }
3246 else
3247 {
3248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3249 "sme_StopBatchScanInd returned failure halStatus %d",
3250 halStatus);
3251 ret = -EINVAL;
3252 goto exit;
3253 }
3254 }
3255 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3256 {
3257 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3258 {
3259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3260 "%s: Batch scan feature is not supported by FW", __func__);
3261 ret = -EINVAL;
3262 goto exit;
3263 }
3264
3265 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3266 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3267 {
3268 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3269 "Received WLS_BATCHING_GET command in invalid mode %d "
3270 "WLS_BATCHING_GET is only allowed in infra STA/P2P client"
3271 " mode",
3272 pAdapter->device_mode);
3273 ret = -EINVAL;
3274 goto exit;
3275 }
3276
3277 priv_data.used_len = 16;
3278 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3279 }
3280#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003281 else {
3282 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3283 __func__, command);
3284 }
3285
Jeff Johnson295189b2012-06-20 16:38:30 -07003286 }
3287exit:
3288 if (command)
3289 {
3290 kfree(command);
3291 }
3292 return ret;
3293}
3294
Srinivas Girigowdade697412013-02-14 16:31:48 -08003295#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3296void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3297{
3298 eCsrBand band = -1;
3299 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3300 switch (band)
3301 {
3302 case eCSR_BAND_ALL:
3303 *pBand = WLAN_HDD_UI_BAND_AUTO;
3304 break;
3305
3306 case eCSR_BAND_24:
3307 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3308 break;
3309
3310 case eCSR_BAND_5G:
3311 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3312 break;
3313
3314 default:
3315 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3316 *pBand = -1;
3317 break;
3318 }
3319}
3320
3321/**---------------------------------------------------------------------------
3322
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003323 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3324
3325 This function parses the send action frame data passed in the format
3326 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3327
Srinivas Girigowda56076852013-08-20 14:00:50 -07003328 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003329 \param - pTargetApBssid Pointer to target Ap bssid
3330 \param - pChannel Pointer to the Target AP channel
3331 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3332 \param - pBuf Pointer to data
3333 \param - pBufLen Pointer to data length
3334
3335 \return - 0 for success non-zero for failure
3336
3337 --------------------------------------------------------------------------*/
3338VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3339 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3340{
3341 tANI_U8 *inPtr = pValue;
3342 tANI_U8 *dataEnd;
3343 int tempInt;
3344 int j = 0;
3345 int i = 0;
3346 int v = 0;
3347 tANI_U8 tempBuf[32];
3348 tANI_U8 tempByte = 0;
3349
3350 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3351 /*no argument after the command*/
3352 if (NULL == inPtr)
3353 {
3354 return -EINVAL;
3355 }
3356
3357 /*no space after the command*/
3358 else if (SPACE_ASCII_VALUE != *inPtr)
3359 {
3360 return -EINVAL;
3361 }
3362
3363 /*removing empty spaces*/
3364 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3365
3366 /*no argument followed by spaces*/
3367 if ('\0' == *inPtr)
3368 {
3369 return -EINVAL;
3370 }
3371
3372 /*getting the first argument ie the target AP bssid */
3373 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
3374 {
3375 return -EINVAL;
3376 }
3377 j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
3378 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
3379 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
3380
3381 /* point to the next argument */
3382 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3383 /*no argument after the command*/
3384 if (NULL == inPtr) return -EINVAL;
3385
3386 /*removing empty spaces*/
3387 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3388
3389 /*no argument followed by spaces*/
3390 if ('\0' == *inPtr)
3391 {
3392 return -EINVAL;
3393 }
3394
3395 /*getting the next argument ie the channel number */
Jeff Johnson440b9472013-04-16 17:35:57 -07003396 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003397 v = kstrtos32(tempBuf, 10, &tempInt);
3398 if ( v < 0) return -EINVAL;
3399
3400 *pChannel = tempInt;
3401
3402 /* point to the next argument */
3403 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3404 /*no argument after the command*/
3405 if (NULL == inPtr) return -EINVAL;
3406 /*removing empty spaces*/
3407 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3408
3409 /*no argument followed by spaces*/
3410 if ('\0' == *inPtr)
3411 {
3412 return -EINVAL;
3413 }
3414
3415 /*getting the next argument ie the dwell time */
Jeff Johnson440b9472013-04-16 17:35:57 -07003416 j = sscanf(inPtr, "%32s ", tempBuf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003417 v = kstrtos32(tempBuf, 10, &tempInt);
3418 if ( v < 0) return -EINVAL;
3419
3420 *pDwellTime = tempInt;
3421
3422 /* point to the next argument */
3423 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3424 /*no argument after the command*/
3425 if (NULL == inPtr) return -EINVAL;
3426 /*removing empty spaces*/
3427 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3428
3429 /*no argument followed by spaces*/
3430 if ('\0' == *inPtr)
3431 {
3432 return -EINVAL;
3433 }
3434
3435 /* find the length of data */
3436 dataEnd = inPtr;
3437 while(('\0' != *dataEnd) )
3438 {
3439 dataEnd++;
3440 ++(*pBufLen);
3441 }
3442 if ( *pBufLen <= 0) return -EINVAL;
3443
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07003444 /* Allocate the number of bytes based on the number of input characters
3445 whether it is even or odd.
3446 if the number of input characters are even, then we need N/2 byte.
3447 if the number of input characters are odd, then we need do (N+1)/2 to
3448 compensate rounding off.
3449 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
3450 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
3451 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003452 if (NULL == *pBuf)
3453 {
3454 hddLog(VOS_TRACE_LEVEL_FATAL,
3455 "%s: vos_mem_alloc failed ", __func__);
3456 return -EINVAL;
3457 }
3458
3459 /* the buffer received from the upper layer is character buffer,
3460 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
3461 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
3462 and f0 in 3rd location */
3463 for (i = 0, j = 0; j < *pBufLen; j += 2)
3464 {
3465 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
3466 (*pBuf)[i++] = tempByte;
3467 }
3468 *pBufLen = i;
3469 return VOS_STATUS_SUCCESS;
3470}
3471
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003472/**---------------------------------------------------------------------------
3473
Srinivas Girigowdade697412013-02-14 16:31:48 -08003474 \brief hdd_parse_channellist() - HDD Parse channel list
3475
3476 This function parses the channel list passed in the format
3477 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003478 if the Number of channels (N) does not match with the actual number of channels passed
3479 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
3480 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
3481 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
3482 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08003483
3484 \param - pValue Pointer to input channel list
3485 \param - ChannelList Pointer to local output array to record channel list
3486 \param - pNumChannels Pointer to number of roam scan channels
3487
3488 \return - 0 for success non-zero for failure
3489
3490 --------------------------------------------------------------------------*/
3491VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
3492{
3493 tANI_U8 *inPtr = pValue;
3494 int tempInt;
3495 int j = 0;
3496 int v = 0;
3497 char buf[32];
3498
3499 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3500 /*no argument after the command*/
3501 if (NULL == inPtr)
3502 {
3503 return -EINVAL;
3504 }
3505
3506 /*no space after the command*/
3507 else if (SPACE_ASCII_VALUE != *inPtr)
3508 {
3509 return -EINVAL;
3510 }
3511
3512 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003513 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003514
3515 /*no argument followed by spaces*/
3516 if ('\0' == *inPtr)
3517 {
3518 return -EINVAL;
3519 }
3520
3521 /*getting the first argument ie the number of channels*/
Chilam Ngc4244af2013-04-01 15:37:32 -07003522 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003523 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003524 if ((v < 0) ||
3525 (tempInt <= 0) ||
3526 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
3527 {
3528 return -EINVAL;
3529 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003530
3531 *pNumChannels = tempInt;
3532
3533 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3534 "Number of channels are: %d", *pNumChannels);
3535
3536 for (j = 0; j < (*pNumChannels); j++)
3537 {
3538 /*inPtr pointing to the beginning of first space after number of channels*/
3539 inPtr = strpbrk( inPtr, " " );
3540 /*no channel list after the number of channels argument*/
3541 if (NULL == inPtr)
3542 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003543 if (0 != j)
3544 {
3545 *pNumChannels = j;
3546 return VOS_STATUS_SUCCESS;
3547 }
3548 else
3549 {
3550 return -EINVAL;
3551 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003552 }
3553
3554 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003555 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003556
3557 /*no channel list after the number of channels argument and spaces*/
3558 if ( '\0' == *inPtr )
3559 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003560 if (0 != j)
3561 {
3562 *pNumChannels = j;
3563 return VOS_STATUS_SUCCESS;
3564 }
3565 else
3566 {
3567 return -EINVAL;
3568 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003569 }
3570
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003571 sscanf(inPtr, "%32s ", buf);
Srinivas Girigowdade697412013-02-14 16:31:48 -08003572 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003573 if ((v < 0) ||
3574 (tempInt <= 0) ||
3575 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3576 {
3577 return -EINVAL;
3578 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003579 pChannelList[j] = tempInt;
3580
3581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3582 "Channel %d added to preferred channel list",
3583 pChannelList[j] );
3584 }
3585
Srinivas Girigowdade697412013-02-14 16:31:48 -08003586 return VOS_STATUS_SUCCESS;
3587}
3588
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003589
3590/**---------------------------------------------------------------------------
3591
3592 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
3593
3594 This function parses the reasoc command data passed in the format
3595 REASSOC<space><bssid><space><channel>
3596
Srinivas Girigowda56076852013-08-20 14:00:50 -07003597 \param - pValue Pointer to input data
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003598 \param - pTargetApBssid Pointer to target Ap bssid
3599 \param - pChannel Pointer to the Target AP channel
3600
3601 \return - 0 for success non-zero for failure
3602
3603 --------------------------------------------------------------------------*/
3604VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
3605{
3606 tANI_U8 *inPtr = pValue;
3607 int tempInt;
3608 int v = 0;
3609 tANI_U8 tempBuf[32];
3610
3611 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3612 /*no argument after the command*/
3613 if (NULL == inPtr)
3614 {
3615 return -EINVAL;
3616 }
3617
3618 /*no space after the command*/
3619 else if (SPACE_ASCII_VALUE != *inPtr)
3620 {
3621 return -EINVAL;
3622 }
3623
3624 /*removing empty spaces*/
3625 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3626
3627 /*no argument followed by spaces*/
3628 if ('\0' == *inPtr)
3629 {
3630 return -EINVAL;
3631 }
3632
3633 /*getting the first argument ie the target AP bssid */
3634 if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':')
3635 {
3636 return -EINVAL;
3637 }
3638 sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1],
3639 (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3],
3640 (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]);
3641
3642 /* point to the next argument */
3643 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3644 /*no argument after the command*/
3645 if (NULL == inPtr) return -EINVAL;
3646
3647 /*removing empty spaces*/
3648 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3649
3650 /*no argument followed by spaces*/
3651 if ('\0' == *inPtr)
3652 {
3653 return -EINVAL;
3654 }
3655
3656 /*getting the next argument ie the channel number */
3657 sscanf(inPtr, "%s ", tempBuf);
3658 v = kstrtos32(tempBuf, 10, &tempInt);
3659 if ( v < 0) return -EINVAL;
3660
3661 *pChannel = tempInt;
3662 return VOS_STATUS_SUCCESS;
3663}
3664
3665#endif
3666
Jeff Johnson295189b2012-06-20 16:38:30 -07003667/**---------------------------------------------------------------------------
3668
3669 \brief hdd_open() - HDD Open function
3670
3671 This is called in response to ifconfig up
3672
3673 \param - dev Pointer to net_device structure
3674
3675 \return - 0 for success non-zero for failure
3676
3677 --------------------------------------------------------------------------*/
3678int hdd_open (struct net_device *dev)
3679{
3680 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3681 hdd_context_t *pHddCtx;
3682 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3683 VOS_STATUS status;
3684 v_BOOL_t in_standby = TRUE;
3685
3686 if (NULL == pAdapter)
3687 {
3688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003689 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003690 return -ENODEV;
3691 }
3692
3693 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3694 if (NULL == pHddCtx)
3695 {
3696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003697 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003698 return -ENODEV;
3699 }
3700
3701 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3702 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
3703 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003704 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
3705 {
3706 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05303707 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003708 in_standby = FALSE;
3709 break;
3710 }
3711 else
3712 {
3713 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3714 pAdapterNode = pNext;
3715 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003716 }
3717
3718 if (TRUE == in_standby)
3719 {
3720 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
3721 {
3722 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
3723 "wlan out of power save", __func__);
3724 return -EINVAL;
3725 }
3726 }
3727
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003728 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07003729 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3730 {
3731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003732 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003733 /* Enable TX queues only when we are connected */
3734 netif_tx_start_all_queues(dev);
3735 }
3736
3737 return 0;
3738}
3739
3740int hdd_mon_open (struct net_device *dev)
3741{
3742 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3743
3744 if(pAdapter == NULL) {
3745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003746 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003747 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003748 }
3749
3750 netif_start_queue(dev);
3751
3752 return 0;
3753}
3754/**---------------------------------------------------------------------------
3755
3756 \brief hdd_stop() - HDD stop function
3757
3758 This is called in response to ifconfig down
3759
3760 \param - dev Pointer to net_device structure
3761
3762 \return - 0 for success non-zero for failure
3763
3764 --------------------------------------------------------------------------*/
3765
3766int hdd_stop (struct net_device *dev)
3767{
3768 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3769 hdd_context_t *pHddCtx;
3770 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3771 VOS_STATUS status;
3772 v_BOOL_t enter_standby = TRUE;
3773
3774 ENTER();
3775
3776 if (NULL == pAdapter)
3777 {
3778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003779 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003780 return -ENODEV;
3781 }
3782
3783 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3784 if (NULL == pHddCtx)
3785 {
3786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003787 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003788 return -ENODEV;
3789 }
3790
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003791 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07003792 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
3793 netif_tx_disable(pAdapter->dev);
3794 netif_carrier_off(pAdapter->dev);
3795
3796
3797 /* SoftAP ifaces should never go in power save mode
3798 making sure same here. */
3799 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
3800 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07003801 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07003802 )
3803 {
3804 /* SoftAP mode, so return from here */
3805 EXIT();
3806 return 0;
3807 }
3808
3809 /* Find if any iface is up then
3810 if any iface is up then can't put device to sleep/ power save mode. */
3811 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3812 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
3813 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003814 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
3815 {
3816 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05303817 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003818 enter_standby = FALSE;
3819 break;
3820 }
3821 else
3822 {
3823 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3824 pAdapterNode = pNext;
3825 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003826 }
3827
3828 if (TRUE == enter_standby)
3829 {
3830 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
3831 "entering standby", __func__);
3832 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
3833 {
3834 /*log and return success*/
3835 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
3836 "wlan in power save", __func__);
3837 }
3838 }
3839
3840 EXIT();
3841 return 0;
3842}
3843
3844/**---------------------------------------------------------------------------
3845
3846 \brief hdd_uninit() - HDD uninit function
3847
3848 This is called during the netdev unregister to uninitialize all data
3849associated with the device
3850
3851 \param - dev Pointer to net_device structure
3852
3853 \return - void
3854
3855 --------------------------------------------------------------------------*/
3856static void hdd_uninit (struct net_device *dev)
3857{
3858 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3859
3860 ENTER();
3861
3862 do
3863 {
3864 if (NULL == pAdapter)
3865 {
3866 hddLog(VOS_TRACE_LEVEL_FATAL,
3867 "%s: NULL pAdapter", __func__);
3868 break;
3869 }
3870
3871 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3872 {
3873 hddLog(VOS_TRACE_LEVEL_FATAL,
3874 "%s: Invalid magic", __func__);
3875 break;
3876 }
3877
3878 if (NULL == pAdapter->pHddCtx)
3879 {
3880 hddLog(VOS_TRACE_LEVEL_FATAL,
3881 "%s: NULL pHddCtx", __func__);
3882 break;
3883 }
3884
3885 if (dev != pAdapter->dev)
3886 {
3887 hddLog(VOS_TRACE_LEVEL_FATAL,
3888 "%s: Invalid device reference", __func__);
3889 /* we haven't validated all cases so let this go for now */
3890 }
3891
3892 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
3893
3894 /* after uninit our adapter structure will no longer be valid */
3895 pAdapter->dev = NULL;
3896 pAdapter->magic = 0;
3897 } while (0);
3898
3899 EXIT();
3900}
3901
3902/**---------------------------------------------------------------------------
3903
3904 \brief hdd_release_firmware() -
3905
3906 This function calls the release firmware API to free the firmware buffer.
3907
3908 \param - pFileName Pointer to the File Name.
3909 pCtx - Pointer to the adapter .
3910
3911
3912 \return - 0 for success, non zero for failure
3913
3914 --------------------------------------------------------------------------*/
3915
3916VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
3917{
3918 VOS_STATUS status = VOS_STATUS_SUCCESS;
3919 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
3920 ENTER();
3921
3922
3923 if (!strcmp(WLAN_FW_FILE, pFileName)) {
3924
3925 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
3926
3927 if(pHddCtx->fw) {
3928 release_firmware(pHddCtx->fw);
3929 pHddCtx->fw = NULL;
3930 }
3931 else
3932 status = VOS_STATUS_E_FAILURE;
3933 }
3934 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
3935 if(pHddCtx->nv) {
3936 release_firmware(pHddCtx->nv);
3937 pHddCtx->nv = NULL;
3938 }
3939 else
3940 status = VOS_STATUS_E_FAILURE;
3941
3942 }
3943
3944 EXIT();
3945 return status;
3946}
3947
3948/**---------------------------------------------------------------------------
3949
3950 \brief hdd_request_firmware() -
3951
3952 This function reads the firmware file using the request firmware
3953 API and returns the the firmware data and the firmware file size.
3954
3955 \param - pfileName - Pointer to the file name.
3956 - pCtx - Pointer to the adapter .
3957 - ppfw_data - Pointer to the pointer of the firmware data.
3958 - pSize - Pointer to the file size.
3959
3960 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
3961
3962 --------------------------------------------------------------------------*/
3963
3964
3965VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
3966{
3967 int status;
3968 VOS_STATUS retval = VOS_STATUS_SUCCESS;
3969 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
3970 ENTER();
3971
3972 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
3973
3974 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
3975
3976 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
3977 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
3978 __func__, pfileName);
3979 retval = VOS_STATUS_E_FAILURE;
3980 }
3981
3982 else {
3983 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
3984 *pSize = pHddCtx->fw->size;
3985 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
3986 __func__, *pSize);
3987 }
3988 }
3989 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
3990
3991 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
3992
3993 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
3994 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
3995 __func__, pfileName);
3996 retval = VOS_STATUS_E_FAILURE;
3997 }
3998
3999 else {
4000 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4001 *pSize = pHddCtx->nv->size;
4002 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4003 __func__, *pSize);
4004 }
4005 }
4006
4007 EXIT();
4008 return retval;
4009}
4010/**---------------------------------------------------------------------------
4011 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4012
4013 This is the function invoked by SME to inform the result of a full power
4014 request issued by HDD
4015
4016 \param - callbackcontext - Pointer to cookie
4017 status - result of request
4018
4019 \return - None
4020
4021--------------------------------------------------------------------------*/
4022void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4023{
4024 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4025
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004026 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004027 if(&pHddCtx->full_pwr_comp_var)
4028 {
4029 complete(&pHddCtx->full_pwr_comp_var);
4030 }
4031}
4032
4033/**---------------------------------------------------------------------------
4034
4035 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4036
4037 This is the function invoked by SME to inform the result of BMPS
4038 request issued by HDD
4039
4040 \param - callbackcontext - Pointer to cookie
4041 status - result of request
4042
4043 \return - None
4044
4045--------------------------------------------------------------------------*/
4046void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4047{
4048
4049 struct completion *completion_var = (struct completion*) callbackContext;
4050
4051 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4052 if(completion_var != NULL)
4053 {
4054 complete(completion_var);
4055 }
4056}
4057
4058/**---------------------------------------------------------------------------
4059
4060 \brief hdd_get_cfg_file_size() -
4061
4062 This function reads the configuration file using the request firmware
4063 API and returns the configuration file size.
4064
4065 \param - pCtx - Pointer to the adapter .
4066 - pFileName - Pointer to the file name.
4067 - pBufSize - Pointer to the buffer size.
4068
4069 \return - 0 for success, non zero for failure
4070
4071 --------------------------------------------------------------------------*/
4072
4073VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4074{
4075 int status;
4076 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4077
4078 ENTER();
4079
4080 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4081
4082 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4083 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4084 status = VOS_STATUS_E_FAILURE;
4085 }
4086 else {
4087 *pBufSize = pHddCtx->fw->size;
4088 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4089 release_firmware(pHddCtx->fw);
4090 pHddCtx->fw = NULL;
4091 }
4092
4093 EXIT();
4094 return VOS_STATUS_SUCCESS;
4095}
4096
4097/**---------------------------------------------------------------------------
4098
4099 \brief hdd_read_cfg_file() -
4100
4101 This function reads the configuration file using the request firmware
4102 API and returns the cfg data and the buffer size of the configuration file.
4103
4104 \param - pCtx - Pointer to the adapter .
4105 - pFileName - Pointer to the file name.
4106 - pBuffer - Pointer to the data buffer.
4107 - pBufSize - Pointer to the buffer size.
4108
4109 \return - 0 for success, non zero for failure
4110
4111 --------------------------------------------------------------------------*/
4112
4113VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4114 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4115{
4116 int status;
4117 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4118
4119 ENTER();
4120
4121 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4122
4123 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4124 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4125 return VOS_STATUS_E_FAILURE;
4126 }
4127 else {
4128 if(*pBufSize != pHddCtx->fw->size) {
4129 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4130 "file size", __func__);
4131 release_firmware(pHddCtx->fw);
4132 pHddCtx->fw = NULL;
4133 return VOS_STATUS_E_FAILURE;
4134 }
4135 else {
4136 if(pBuffer) {
4137 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4138 }
4139 release_firmware(pHddCtx->fw);
4140 pHddCtx->fw = NULL;
4141 }
4142 }
4143
4144 EXIT();
4145
4146 return VOS_STATUS_SUCCESS;
4147}
4148
4149/**---------------------------------------------------------------------------
4150
Jeff Johnson295189b2012-06-20 16:38:30 -07004151 \brief hdd_set_mac_address() -
4152
4153 This function sets the user specified mac address using
4154 the command ifconfig wlanX hw ether <mac adress>.
4155
4156 \param - dev - Pointer to the net device.
4157 - addr - Pointer to the sockaddr.
4158 \return - 0 for success, non zero for failure
4159
4160 --------------------------------------------------------------------------*/
4161
4162static int hdd_set_mac_address(struct net_device *dev, void *addr)
4163{
4164 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4165 struct sockaddr *psta_mac_addr = addr;
4166 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4167
4168 ENTER();
4169
4170 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4171
4172#ifdef HDD_SESSIONIZE
4173 // set the MAC address though the STA ID CFG.
4174 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4175 (v_U8_t *)&pAdapter->macAddressCurrent,
4176 sizeof( pAdapter->macAddressCurrent ),
4177 hdd_set_mac_addr_cb, VOS_FALSE );
4178#endif
4179
4180 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4181
4182 EXIT();
4183 return halStatus;
4184}
4185
4186tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4187{
4188 int i;
4189 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4190 {
4191 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4192 break;
4193 }
4194
4195 if( VOS_MAX_CONCURRENCY_PERSONA == i)
4196 return NULL;
4197
4198 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
4199 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
4200}
4201
4202void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
4203{
4204 int i;
4205 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4206 {
4207 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
4208 {
4209 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
4210 break;
4211 }
4212 }
4213 return;
4214}
4215
4216#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4217 static struct net_device_ops wlan_drv_ops = {
4218 .ndo_open = hdd_open,
4219 .ndo_stop = hdd_stop,
4220 .ndo_uninit = hdd_uninit,
4221 .ndo_start_xmit = hdd_hard_start_xmit,
4222 .ndo_tx_timeout = hdd_tx_timeout,
4223 .ndo_get_stats = hdd_stats,
4224 .ndo_do_ioctl = hdd_ioctl,
4225 .ndo_set_mac_address = hdd_set_mac_address,
4226 .ndo_select_queue = hdd_select_queue,
4227#ifdef WLAN_FEATURE_PACKET_FILTERING
4228#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
4229 .ndo_set_rx_mode = hdd_set_multicast_list,
4230#else
4231 .ndo_set_multicast_list = hdd_set_multicast_list,
4232#endif //LINUX_VERSION_CODE
4233#endif
4234 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004235 static struct net_device_ops wlan_mon_drv_ops = {
4236 .ndo_open = hdd_mon_open,
4237 .ndo_stop = hdd_stop,
4238 .ndo_uninit = hdd_uninit,
4239 .ndo_start_xmit = hdd_mon_hard_start_xmit,
4240 .ndo_tx_timeout = hdd_tx_timeout,
4241 .ndo_get_stats = hdd_stats,
4242 .ndo_do_ioctl = hdd_ioctl,
4243 .ndo_set_mac_address = hdd_set_mac_address,
4244 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004245
4246#endif
4247
4248void hdd_set_station_ops( struct net_device *pWlanDev )
4249{
4250#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4251 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
4252 pWlanDev->netdev_ops = &wlan_drv_ops;
4253#else
4254 pWlanDev->open = hdd_open;
4255 pWlanDev->stop = hdd_stop;
4256 pWlanDev->uninit = hdd_uninit;
4257 pWlanDev->hard_start_xmit = NULL;
4258 pWlanDev->tx_timeout = hdd_tx_timeout;
4259 pWlanDev->get_stats = hdd_stats;
4260 pWlanDev->do_ioctl = hdd_ioctl;
4261 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
4262 pWlanDev->set_mac_address = hdd_set_mac_address;
4263#endif
4264}
4265
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004266static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07004267{
4268 struct net_device *pWlanDev = NULL;
4269 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004270 /*
4271 * cfg80211 initialization and registration....
4272 */
4273 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
4274
Jeff Johnson295189b2012-06-20 16:38:30 -07004275 if(pWlanDev != NULL)
4276 {
4277
4278 //Save the pointer to the net_device in the HDD adapter
4279 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
4280
Jeff Johnson295189b2012-06-20 16:38:30 -07004281 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
4282
4283 pAdapter->dev = pWlanDev;
4284 pAdapter->pHddCtx = pHddCtx;
4285 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
4286
4287 init_completion(&pAdapter->session_open_comp_var);
4288 init_completion(&pAdapter->session_close_comp_var);
4289 init_completion(&pAdapter->disconnect_comp_var);
4290 init_completion(&pAdapter->linkup_event_var);
4291 init_completion(&pAdapter->cancel_rem_on_chan_var);
4292 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004293#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4294 init_completion(&pAdapter->offchannel_tx_event);
4295#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004296 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004297#ifdef FEATURE_WLAN_TDLS
4298 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07004299 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08004300 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05304301 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004302#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004303 init_completion(&pHddCtx->mc_sus_event_var);
4304 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05304305 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07004306 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07004307 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07004308
Rajeev79dbe4c2013-10-05 11:03:42 +05304309#ifdef FEATURE_WLAN_BATCH_SCAN
4310 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
4311 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
4312 pAdapter->pBatchScanRsp = NULL;
4313 pAdapter->numScanList = 0;
4314 mutex_init(&pAdapter->hdd_batch_scan_lock);
4315#endif
4316
Jeff Johnson295189b2012-06-20 16:38:30 -07004317 pAdapter->isLinkUpSvcNeeded = FALSE;
4318 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
4319 //Init the net_device structure
4320 strlcpy(pWlanDev->name, name, IFNAMSIZ);
4321
4322 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
4323 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
4324 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
4325 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
4326
4327 hdd_set_station_ops( pAdapter->dev );
4328
4329 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004330 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
4331 pAdapter->wdev.wiphy = pHddCtx->wiphy;
4332 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004333 /* set pWlanDev's parent to underlying device */
4334 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
4335 }
4336
4337 return pAdapter;
4338}
4339
4340VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
4341{
4342 struct net_device *pWlanDev = pAdapter->dev;
4343 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4344 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4345 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4346
4347 if( rtnl_lock_held )
4348 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08004349 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07004350 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
4351 {
4352 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
4353 return VOS_STATUS_E_FAILURE;
4354 }
4355 }
4356 if (register_netdevice(pWlanDev))
4357 {
4358 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
4359 return VOS_STATUS_E_FAILURE;
4360 }
4361 }
4362 else
4363 {
4364 if(register_netdev(pWlanDev))
4365 {
4366 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
4367 return VOS_STATUS_E_FAILURE;
4368 }
4369 }
4370 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
4371
4372 return VOS_STATUS_SUCCESS;
4373}
4374
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004375static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07004376{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004377 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07004378
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004379 if (NULL == pAdapter)
4380 {
4381 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
4382 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07004383 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004384
4385 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4386 {
4387 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
4388 return eHAL_STATUS_NOT_INITIALIZED;
4389 }
4390
4391 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
4392
4393 /* need to make sure all of our scheduled work has completed.
4394 * This callback is called from MC thread context, so it is safe to
4395 * to call below flush workqueue API from here.
4396 */
4397 flush_scheduled_work();
4398
4399 /* We can be blocked while waiting for scheduled work to be
4400 * flushed, and the adapter structure can potentially be freed, in
4401 * which case the magic will have been reset. So make sure the
4402 * magic is still good, and hence the adapter structure is still
4403 * valid, before signaling completion */
4404 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
4405 {
4406 complete(&pAdapter->session_close_comp_var);
4407 }
4408
Jeff Johnson295189b2012-06-20 16:38:30 -07004409 return eHAL_STATUS_SUCCESS;
4410}
4411
4412VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
4413{
4414 struct net_device *pWlanDev = pAdapter->dev;
4415 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4416 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4417 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4418 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4419 int rc = 0;
4420
4421 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004422 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07004423 //Open a SME session for future operation
4424 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004425 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004426 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4427 {
4428 hddLog(VOS_TRACE_LEVEL_FATAL,
4429 "sme_OpenSession() failed with status code %08d [x%08lx]",
4430 halStatus, halStatus );
4431 status = VOS_STATUS_E_FAILURE;
4432 goto error_sme_open;
4433 }
4434
4435 //Block on a completion variable. Can't wait forever though.
4436 rc = wait_for_completion_interruptible_timeout(
4437 &pAdapter->session_open_comp_var,
4438 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4439 if (!rc)
4440 {
4441 hddLog(VOS_TRACE_LEVEL_FATAL,
4442 "Session is not opened within timeout period code %08d", rc );
4443 status = VOS_STATUS_E_FAILURE;
4444 goto error_sme_open;
4445 }
4446
4447 // Register wireless extensions
4448 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
4449 {
4450 hddLog(VOS_TRACE_LEVEL_FATAL,
4451 "hdd_register_wext() failed with status code %08d [x%08lx]",
4452 halStatus, halStatus );
4453 status = VOS_STATUS_E_FAILURE;
4454 goto error_register_wext;
4455 }
4456 //Safe to register the hard_start_xmit function again
4457#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4458 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
4459#else
4460 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
4461#endif
4462
4463 //Set the Connection State to Not Connected
4464 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4465
4466 //Set the default operation channel
4467 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
4468
4469 /* Make the default Auth Type as OPEN*/
4470 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4471
4472 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
4473 {
4474 hddLog(VOS_TRACE_LEVEL_FATAL,
4475 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
4476 status, status );
4477 goto error_init_txrx;
4478 }
4479
4480 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4481
4482 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
4483 {
4484 hddLog(VOS_TRACE_LEVEL_FATAL,
4485 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
4486 status, status );
4487 goto error_wmm_init;
4488 }
4489
4490 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4491
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004492#ifdef FEATURE_WLAN_TDLS
4493 if(0 != wlan_hdd_tdls_init(pAdapter))
4494 {
4495 status = VOS_STATUS_E_FAILURE;
4496 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
4497 goto error_tdls_init;
4498 }
4499 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
4500#endif
4501
Jeff Johnson295189b2012-06-20 16:38:30 -07004502 return VOS_STATUS_SUCCESS;
4503
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004504#ifdef FEATURE_WLAN_TDLS
4505error_tdls_init:
4506 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4507 hdd_wmm_adapter_close(pAdapter);
4508#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004509error_wmm_init:
4510 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4511 hdd_deinit_tx_rx(pAdapter);
4512error_init_txrx:
4513 hdd_UnregisterWext(pWlanDev);
4514error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004515 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07004516 {
4517 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004518 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07004519 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004520 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07004521 {
4522 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004523 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004524 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004525 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07004526 }
4527}
4528error_sme_open:
4529 return status;
4530}
4531
Jeff Johnson295189b2012-06-20 16:38:30 -07004532void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4533{
4534 hdd_cfg80211_state_t *cfgState;
4535
4536 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
4537
4538 if( NULL != cfgState->buf )
4539 {
4540 int rc;
4541 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
4542 rc = wait_for_completion_interruptible_timeout(
4543 &pAdapter->tx_action_cnf_event,
4544 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
4545 if(!rc)
4546 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08004547 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
4549 }
4550 }
4551 return;
4552}
Jeff Johnson295189b2012-06-20 16:38:30 -07004553
4554void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4555{
4556 ENTER();
4557 switch ( pAdapter->device_mode )
4558 {
4559 case WLAN_HDD_INFRA_STATION:
4560 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004561 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004562 {
4563 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
4564 {
4565 hdd_deinit_tx_rx( pAdapter );
4566 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4567 }
4568
4569 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
4570 {
4571 hdd_wmm_adapter_close( pAdapter );
4572 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4573 }
4574
Jeff Johnson295189b2012-06-20 16:38:30 -07004575 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004576#ifdef FEATURE_WLAN_TDLS
4577 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
4578 {
4579 wlan_hdd_tdls_exit(pAdapter);
4580 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
4581 }
4582#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004583
4584 break;
4585 }
4586
4587 case WLAN_HDD_SOFTAP:
4588 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004589 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05304590
4591 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
4592 {
4593 hdd_wmm_adapter_close( pAdapter );
4594 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4595 }
4596
Jeff Johnson295189b2012-06-20 16:38:30 -07004597 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004598
4599 hdd_unregister_hostapd(pAdapter);
4600 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07004601 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07004602 break;
4603 }
4604
4605 case WLAN_HDD_MONITOR:
4606 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004607 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
4609 {
4610 hdd_deinit_tx_rx( pAdapter );
4611 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4612 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004613 if(NULL != pAdapterforTx)
4614 {
4615 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
4616 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004617 break;
4618 }
4619
4620
4621 default:
4622 break;
4623 }
4624
4625 EXIT();
4626}
4627
4628void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
4629{
4630 struct net_device *pWlanDev = pAdapter->dev;
4631
Rajeev79dbe4c2013-10-05 11:03:42 +05304632#ifdef FEATURE_WLAN_BATCH_SCAN
4633 tHddBatchScanRsp *pNode;
4634 tHddBatchScanRsp *pPrev;
4635 if (pAdapter)
4636 {
4637 mutex_lock(&pAdapter->hdd_batch_scan_lock);
4638 pNode = pAdapter->pBatchScanRsp;
4639 while (pNode)
4640 {
4641 pPrev = pNode;
4642 pNode = pNode->pNext;
4643 vos_mem_free((v_VOID_t * )pPrev);
4644 }
4645 pAdapter->pBatchScanRsp = NULL;
4646 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
4647 }
4648#endif
4649
Jeff Johnson295189b2012-06-20 16:38:30 -07004650 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
4651 if( rtnl_held )
4652 {
4653 unregister_netdevice(pWlanDev);
4654 }
4655 else
4656 {
4657 unregister_netdev(pWlanDev);
4658 }
4659 // note that the pAdapter is no longer valid at this point
4660 // since the memory has been reclaimed
4661 }
4662
4663}
4664
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004665void hdd_set_pwrparams(hdd_context_t *pHddCtx)
4666{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304667 VOS_STATUS status;
4668 hdd_adapter_t *pAdapter = NULL;
4669 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004670
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304671 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004672
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304673 /*loop through all adapters.*/
4674 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004675 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304676 pAdapter = pAdapterNode->pAdapter;
4677 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
4678 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004679
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304680 { // we skip this registration for modes other than STA and P2P client modes.
4681 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4682 pAdapterNode = pNext;
4683 continue;
4684 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004685
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304686 //Apply Dynamic DTIM For P2P
4687 //Only if ignoreDynamicDtimInP2pMode is not set in ini
4688 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
4689 pHddCtx->cfg_ini->enableModulatedDTIM) &&
4690 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4691 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
4692 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
4693 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
4694 (eConnectionState_Associated ==
4695 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
4696 (pHddCtx->cfg_ini->fIsBmpsEnabled))
4697 {
4698 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004699
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304700 powerRequest.uIgnoreDTIM = 1;
4701 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
4702
4703 if (pHddCtx->cfg_ini->enableModulatedDTIM)
4704 {
4705 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
4706 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
4707 }
4708 else
4709 {
4710 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
4711 }
4712
4713 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
4714 * specified during Enter/Exit BMPS when LCD off*/
4715 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
4716 NULL, eANI_BOOLEAN_FALSE);
4717 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
4718 NULL, eANI_BOOLEAN_FALSE);
4719
4720 /* switch to the DTIM specified in cfg.ini */
4721 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4722 "Switch to DTIM %d", powerRequest.uListenInterval);
4723 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
4724 break;
4725
4726 }
4727
4728 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4729 pAdapterNode = pNext;
4730 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004731}
4732
4733void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
4734{
4735 /*Switch back to DTIM 1*/
4736 tSirSetPowerParamsReq powerRequest = { 0 };
4737
4738 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
4739 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07004740 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004741
4742 /* Update ignoreDTIM and ListedInterval in CFG with default values */
4743 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
4744 NULL, eANI_BOOLEAN_FALSE);
4745 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
4746 NULL, eANI_BOOLEAN_FALSE);
4747
4748 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4749 "Switch to DTIM%d",powerRequest.uListenInterval);
4750 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
4751
4752}
4753
Jeff Johnson295189b2012-06-20 16:38:30 -07004754VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
4755{
4756 VOS_STATUS status = VOS_STATUS_SUCCESS;
4757
4758 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
4759 {
4760 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4761 }
4762
4763 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
4764 {
4765 sme_StartAutoBmpsTimer(pHddCtx->hHal);
4766 }
4767
4768 if (pHddCtx->cfg_ini->fIsImpsEnabled)
4769 {
4770 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4771 }
4772
4773 return status;
4774}
4775
4776VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
4777{
4778 hdd_adapter_t *pAdapter = NULL;
4779 eHalStatus halStatus;
4780 VOS_STATUS status = VOS_STATUS_E_INVAL;
4781 v_BOOL_t disableBmps = FALSE;
4782 v_BOOL_t disableImps = FALSE;
4783
4784 switch(session_type)
4785 {
4786 case WLAN_HDD_INFRA_STATION:
4787 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07004788 case WLAN_HDD_P2P_CLIENT:
4789 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004790 //Exit BMPS -> Is Sta/P2P Client is already connected
4791 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
4792 if((NULL != pAdapter)&&
4793 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4794 {
4795 disableBmps = TRUE;
4796 }
4797
4798 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4799 if((NULL != pAdapter)&&
4800 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4801 {
4802 disableBmps = TRUE;
4803 }
4804
4805 //Exit both Bmps and Imps incase of Go/SAP Mode
4806 if((WLAN_HDD_SOFTAP == session_type) ||
4807 (WLAN_HDD_P2P_GO == session_type))
4808 {
4809 disableBmps = TRUE;
4810 disableImps = TRUE;
4811 }
4812
4813 if(TRUE == disableImps)
4814 {
4815 if (pHddCtx->cfg_ini->fIsImpsEnabled)
4816 {
4817 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4818 }
4819 }
4820
4821 if(TRUE == disableBmps)
4822 {
4823 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
4824 {
4825 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4826
4827 if(eHAL_STATUS_SUCCESS != halStatus)
4828 {
4829 status = VOS_STATUS_E_FAILURE;
4830 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
4831 VOS_ASSERT(0);
4832 return status;
4833 }
4834 }
4835
4836 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
4837 {
4838 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
4839
4840 if(eHAL_STATUS_SUCCESS != halStatus)
4841 {
4842 status = VOS_STATUS_E_FAILURE;
4843 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
4844 VOS_ASSERT(0);
4845 return status;
4846 }
4847 }
4848 }
4849
4850 if((TRUE == disableBmps) ||
4851 (TRUE == disableImps))
4852 {
4853 /* Now, get the chip into Full Power now */
4854 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
4855 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
4856 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
4857
4858 if(halStatus != eHAL_STATUS_SUCCESS)
4859 {
4860 if(halStatus == eHAL_STATUS_PMC_PENDING)
4861 {
4862 //Block on a completion variable. Can't wait forever though
4863 wait_for_completion_interruptible_timeout(
4864 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
4865 }
4866 else
4867 {
4868 status = VOS_STATUS_E_FAILURE;
4869 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
4870 VOS_ASSERT(0);
4871 return status;
4872 }
4873 }
4874
4875 status = VOS_STATUS_SUCCESS;
4876 }
4877
4878 break;
4879 }
4880 return status;
4881}
4882
4883hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004884 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07004885 tANI_U8 rtnl_held )
4886{
4887 hdd_adapter_t *pAdapter = NULL;
4888 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
4889 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4890 VOS_STATUS exitbmpsStatus;
4891
4892 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
4893
4894 //Disable BMPS incase of Concurrency
4895 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
4896
4897 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
4898 {
4899 //Fail to Exit BMPS
4900 VOS_ASSERT(0);
4901 return NULL;
4902 }
4903
4904 switch(session_type)
4905 {
4906 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004907 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004908 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004909 {
4910 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
4911
4912 if( NULL == pAdapter )
4913 return NULL;
4914
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05304915#ifdef FEATURE_WLAN_TDLS
4916 /* A Mutex Lock is introduced while changing/initializing the mode to
4917 * protect the concurrent access for the Adapters by TDLS module.
4918 */
4919 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
4920 {
4921 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4922 "%s: unable to lock list", __func__);
4923 return NULL;
4924 }
4925#endif
4926
Jeff Johnsone7245742012-09-05 17:12:55 -07004927 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
4928 NL80211_IFTYPE_P2P_CLIENT:
4929 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07004930
Jeff Johnson295189b2012-06-20 16:38:30 -07004931 pAdapter->device_mode = session_type;
4932
4933 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05304934#ifdef FEATURE_WLAN_TDLS
4935 mutex_unlock(&pHddCtx->tdls_lock);
4936#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004937 if( VOS_STATUS_SUCCESS != status )
4938 goto err_free_netdev;
4939
4940 status = hdd_register_interface( pAdapter, rtnl_held );
4941 if( VOS_STATUS_SUCCESS != status )
4942 {
4943 hdd_deinit_adapter(pHddCtx, pAdapter);
4944 goto err_free_netdev;
4945 }
4946 //Stop the Interface TX queue.
4947 netif_tx_disable(pAdapter->dev);
4948 //netif_tx_disable(pWlanDev);
4949 netif_carrier_off(pAdapter->dev);
4950
4951 break;
4952 }
4953
Jeff Johnson295189b2012-06-20 16:38:30 -07004954 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004955 case WLAN_HDD_SOFTAP:
4956 {
4957 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
4958 if( NULL == pAdapter )
4959 return NULL;
4960
Jeff Johnson295189b2012-06-20 16:38:30 -07004961 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
4962 NL80211_IFTYPE_AP:
4963 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07004964 pAdapter->device_mode = session_type;
4965
4966 status = hdd_init_ap_mode(pAdapter);
4967 if( VOS_STATUS_SUCCESS != status )
4968 goto err_free_netdev;
4969
4970 status = hdd_register_hostapd( pAdapter, rtnl_held );
4971 if( VOS_STATUS_SUCCESS != status )
4972 {
4973 hdd_deinit_adapter(pHddCtx, pAdapter);
4974 goto err_free_netdev;
4975 }
4976
4977 netif_tx_disable(pAdapter->dev);
4978 netif_carrier_off(pAdapter->dev);
4979
4980 hdd_set_conparam( 1 );
4981 break;
4982 }
4983 case WLAN_HDD_MONITOR:
4984 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004985 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
4986 if( NULL == pAdapter )
4987 return NULL;
4988
4989 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
4990 pAdapter->device_mode = session_type;
4991 status = hdd_register_interface( pAdapter, rtnl_held );
4992#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
4993 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
4994#else
4995 pAdapter->dev->open = hdd_mon_open;
4996 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
4997#endif
4998 hdd_init_tx_rx( pAdapter );
4999 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5000 //Set adapter to be used for data tx. It will use either GO or softap.
5001 pAdapter->sessionCtx.monitor.pAdapterForTx =
5002 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005003 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5004 {
5005 pAdapter->sessionCtx.monitor.pAdapterForTx =
5006 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5007 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005008 /* This workqueue will be used to transmit management packet over
5009 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005010 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5011 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5012 return NULL;
5013 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005014
Jeff Johnson295189b2012-06-20 16:38:30 -07005015 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5016 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005017 }
5018 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005019 case WLAN_HDD_FTM:
5020 {
5021 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5022
5023 if( NULL == pAdapter )
5024 return NULL;
5025 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5026 * message while loading driver in FTM mode. */
5027 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5028 pAdapter->device_mode = session_type;
5029 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305030
5031 hdd_init_tx_rx( pAdapter );
5032
5033 //Stop the Interface TX queue.
5034 netif_tx_disable(pAdapter->dev);
5035 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005036 }
5037 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005038 default:
5039 {
5040 VOS_ASSERT(0);
5041 return NULL;
5042 }
5043 }
5044
5045
5046 if( VOS_STATUS_SUCCESS == status )
5047 {
5048 //Add it to the hdd's session list.
5049 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5050 if( NULL == pHddAdapterNode )
5051 {
5052 status = VOS_STATUS_E_NOMEM;
5053 }
5054 else
5055 {
5056 pHddAdapterNode->pAdapter = pAdapter;
5057 status = hdd_add_adapter_back ( pHddCtx,
5058 pHddAdapterNode );
5059 }
5060 }
5061
5062 if( VOS_STATUS_SUCCESS != status )
5063 {
5064 if( NULL != pAdapter )
5065 {
5066 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5067 pAdapter = NULL;
5068 }
5069 if( NULL != pHddAdapterNode )
5070 {
5071 vos_mem_free( pHddAdapterNode );
5072 }
5073
5074 goto resume_bmps;
5075 }
5076
5077 if(VOS_STATUS_SUCCESS == status)
5078 {
5079 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5080
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005081 //Initialize the WoWL service
5082 if(!hdd_init_wowl(pAdapter))
5083 {
5084 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5085 goto err_free_netdev;
5086 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005087 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005088 return pAdapter;
5089
5090err_free_netdev:
5091 free_netdev(pAdapter->dev);
5092 wlan_hdd_release_intf_addr( pHddCtx,
5093 pAdapter->macAddressCurrent.bytes );
5094
5095resume_bmps:
5096 //If bmps disabled enable it
5097 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5098 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305099 if (pHddCtx->hdd_wlan_suspended)
5100 {
5101 hdd_set_pwrparams(pHddCtx);
5102 }
5103 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005104 }
5105 return NULL;
5106}
5107
5108VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5109 tANI_U8 rtnl_held )
5110{
5111 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5112 VOS_STATUS status;
5113
5114 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5115 if( VOS_STATUS_SUCCESS != status )
5116 return status;
5117
5118 while ( pCurrent->pAdapter != pAdapter )
5119 {
5120 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5121 if( VOS_STATUS_SUCCESS != status )
5122 break;
5123
5124 pCurrent = pNext;
5125 }
5126 pAdapterNode = pCurrent;
5127 if( VOS_STATUS_SUCCESS == status )
5128 {
5129 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5130 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305131
5132#ifdef FEATURE_WLAN_TDLS
5133
5134 /* A Mutex Lock is introduced while changing/initializing the mode to
5135 * protect the concurrent access for the Adapters by TDLS module.
5136 */
5137 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5138 {
5139 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5140 "%s: unable to lock list", __func__);
5141 return VOS_STATUS_E_FAILURE;
5142 }
5143#endif
5144
Jeff Johnson295189b2012-06-20 16:38:30 -07005145 hdd_remove_adapter( pHddCtx, pAdapterNode );
5146 vos_mem_free( pAdapterNode );
5147
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305148#ifdef FEATURE_WLAN_TDLS
5149 mutex_unlock(&pHddCtx->tdls_lock);
5150#endif
5151
Jeff Johnson295189b2012-06-20 16:38:30 -07005152
5153 /* If there is a single session of STA/P2P client, re-enable BMPS */
5154 if ((!vos_concurrent_sessions_running()) &&
5155 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5156 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5157 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305158 if (pHddCtx->hdd_wlan_suspended)
5159 {
5160 hdd_set_pwrparams(pHddCtx);
5161 }
5162 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005163 }
5164
5165 return VOS_STATUS_SUCCESS;
5166 }
5167
5168 return VOS_STATUS_E_FAILURE;
5169}
5170
5171VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5172{
5173 hdd_adapter_list_node_t *pHddAdapterNode;
5174 VOS_STATUS status;
5175
5176 ENTER();
5177
5178 do
5179 {
5180 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5181 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5182 {
5183 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
5184 vos_mem_free( pHddAdapterNode );
5185 }
5186 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
5187
5188 EXIT();
5189
5190 return VOS_STATUS_SUCCESS;
5191}
5192
5193void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
5194{
5195 v_U8_t addIE[1] = {0};
5196
5197 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5198 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
5199 eANI_BOOLEAN_FALSE) )
5200 {
5201 hddLog(LOGE,
5202 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
5203 }
5204
5205 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5206 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
5207 eANI_BOOLEAN_FALSE) )
5208 {
5209 hddLog(LOGE,
5210 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
5211 }
5212
5213 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5214 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
5215 eANI_BOOLEAN_FALSE) )
5216 {
5217 hddLog(LOGE,
5218 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
5219 }
5220}
5221
5222VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5223{
5224 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5225 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5226 union iwreq_data wrqu;
5227
5228 ENTER();
5229
5230 switch(pAdapter->device_mode)
5231 {
5232 case WLAN_HDD_INFRA_STATION:
5233 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005234 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005235 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5236 {
5237 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
5238 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5239 pAdapter->sessionId,
5240 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5241 else
5242 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5243 pAdapter->sessionId,
5244 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5245 //success implies disconnect command got queued up successfully
5246 if(halStatus == eHAL_STATUS_SUCCESS)
5247 {
5248 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
5249 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5250 }
5251 memset(&wrqu, '\0', sizeof(wrqu));
5252 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5253 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5254 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
5255 }
5256 else
5257 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305258 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005259 }
5260
5261 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
5262 {
5263 INIT_COMPLETION(pAdapter->session_close_comp_var);
5264 if (eHAL_STATUS_SUCCESS ==
5265 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
5266 hdd_smeCloseSessionCallback, pAdapter))
5267 {
5268 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005269 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005270 &pAdapter->session_close_comp_var,
5271 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5272 }
5273 }
5274
5275 break;
5276
5277 case WLAN_HDD_SOFTAP:
5278 case WLAN_HDD_P2P_GO:
5279 //Any softap specific cleanup here...
5280 mutex_lock(&pHddCtx->sap_lock);
5281 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5282 {
5283 VOS_STATUS status;
5284 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5285
5286 //Stop Bss.
5287 status = WLANSAP_StopBss(pHddCtx->pvosContext);
5288 if (VOS_IS_STATUS_SUCCESS(status))
5289 {
5290 hdd_hostapd_state_t *pHostapdState =
5291 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5292
5293 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
5294
5295 if (!VOS_IS_STATUS_SUCCESS(status))
5296 {
5297 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005298 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005299 }
5300 }
5301 else
5302 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005303 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005304 }
5305 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
5306
5307 if (eHAL_STATUS_FAILURE ==
5308 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5309 0, NULL, eANI_BOOLEAN_FALSE))
5310 {
5311 hddLog(LOGE,
5312 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005313 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005314 }
5315
5316 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
5317 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5318 eANI_BOOLEAN_FALSE) )
5319 {
5320 hddLog(LOGE,
5321 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
5322 }
5323
5324 // Reset WNI_CFG_PROBE_RSP Flags
5325 wlan_hdd_reset_prob_rspies(pAdapter);
5326 kfree(pAdapter->sessionCtx.ap.beacon);
5327 pAdapter->sessionCtx.ap.beacon = NULL;
5328 }
5329 mutex_unlock(&pHddCtx->sap_lock);
5330 break;
5331 case WLAN_HDD_MONITOR:
5332 break;
5333 default:
5334 break;
5335 }
5336
5337 EXIT();
5338 return VOS_STATUS_SUCCESS;
5339}
5340
5341VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
5342{
5343 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5344 VOS_STATUS status;
5345 hdd_adapter_t *pAdapter;
5346
5347 ENTER();
5348
5349 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5350
5351 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5352 {
5353 pAdapter = pAdapterNode->pAdapter;
5354 netif_tx_disable(pAdapter->dev);
5355 netif_carrier_off(pAdapter->dev);
5356
5357 hdd_stop_adapter( pHddCtx, pAdapter );
5358
5359 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5360 pAdapterNode = pNext;
5361 }
5362
5363 EXIT();
5364
5365 return VOS_STATUS_SUCCESS;
5366}
5367
5368VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
5369{
5370 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5371 VOS_STATUS status;
5372 hdd_adapter_t *pAdapter;
5373
5374 ENTER();
5375
5376 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5377
5378 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5379 {
5380 pAdapter = pAdapterNode->pAdapter;
5381 netif_tx_disable(pAdapter->dev);
5382 netif_carrier_off(pAdapter->dev);
5383
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005384 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
5385
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305387 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5388 {
5389 hdd_wmm_adapter_close( pAdapter );
5390 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5391 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005392
5393 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5394 pAdapterNode = pNext;
5395 }
5396
5397 EXIT();
5398
5399 return VOS_STATUS_SUCCESS;
5400}
5401
5402VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
5403{
5404 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5405 VOS_STATUS status;
5406 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305407 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07005408
5409 ENTER();
5410
5411 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5412
5413 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5414 {
5415 pAdapter = pAdapterNode->pAdapter;
5416
5417 switch(pAdapter->device_mode)
5418 {
5419 case WLAN_HDD_INFRA_STATION:
5420 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005421 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305422
5423 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
5424
Jeff Johnson295189b2012-06-20 16:38:30 -07005425 hdd_init_station_mode(pAdapter);
5426 /* Open the gates for HDD to receive Wext commands */
5427 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005428 pHddCtx->scan_info.mScanPending = FALSE;
5429 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005430
5431 //Trigger the initial scan
5432 hdd_wlan_initial_scan(pAdapter);
5433
5434 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305435 if (eConnectionState_Associated == connState ||
5436 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07005437 {
5438 union iwreq_data wrqu;
5439 memset(&wrqu, '\0', sizeof(wrqu));
5440 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5441 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5442 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005443 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005444
Jeff Johnson295189b2012-06-20 16:38:30 -07005445 /* indicate disconnected event to nl80211 */
5446 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
5447 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005448 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305449 else if (eConnectionState_Connecting == connState)
5450 {
5451 /*
5452 * Indicate connect failure to supplicant if we were in the
5453 * process of connecting
5454 */
5455 cfg80211_connect_result(pAdapter->dev, NULL,
5456 NULL, 0, NULL, 0,
5457 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
5458 GFP_KERNEL);
5459 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005460 break;
5461
5462 case WLAN_HDD_SOFTAP:
5463 /* softAP can handle SSR */
5464 break;
5465
5466 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07005467 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07005468 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07005469 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005470 break;
5471
5472 case WLAN_HDD_MONITOR:
5473 /* monitor interface start */
5474 break;
5475 default:
5476 break;
5477 }
5478
5479 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5480 pAdapterNode = pNext;
5481 }
5482
5483 EXIT();
5484
5485 return VOS_STATUS_SUCCESS;
5486}
5487
5488VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
5489{
5490 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5491 hdd_adapter_t *pAdapter;
5492 VOS_STATUS status;
5493 v_U32_t roamId;
5494
5495 ENTER();
5496
5497 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5498
5499 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5500 {
5501 pAdapter = pAdapterNode->pAdapter;
5502
5503 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5504 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5505 {
5506 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5507 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5508
5509 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5510 init_completion(&pAdapter->disconnect_comp_var);
5511 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
5512 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5513
5514 wait_for_completion_interruptible_timeout(
5515 &pAdapter->disconnect_comp_var,
5516 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5517
5518 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
5519 pHddCtx->isAmpAllowed = VOS_FALSE;
5520 sme_RoamConnect(pHddCtx->hHal,
5521 pAdapter->sessionId, &(pWextState->roamProfile),
5522 &roamId);
5523 }
5524
5525 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5526 pAdapterNode = pNext;
5527 }
5528
5529 EXIT();
5530
5531 return VOS_STATUS_SUCCESS;
5532}
5533
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07005534void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
5535{
5536 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5537 VOS_STATUS status;
5538 hdd_adapter_t *pAdapter;
5539 hdd_station_ctx_t *pHddStaCtx;
5540 hdd_ap_ctx_t *pHddApCtx;
5541 hdd_hostapd_state_t * pHostapdState;
5542 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
5543 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
5544 const char *p2pMode = "DEV";
5545 const char *ccMode = "Standalone";
5546 int n;
5547
5548 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5549 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5550 {
5551 pAdapter = pAdapterNode->pAdapter;
5552 switch (pAdapter->device_mode) {
5553 case WLAN_HDD_INFRA_STATION:
5554 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5555 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
5556 staChannel = pHddStaCtx->conn_info.operationChannel;
5557 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
5558 }
5559 break;
5560 case WLAN_HDD_P2P_CLIENT:
5561 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5562 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
5563 p2pChannel = pHddStaCtx->conn_info.operationChannel;
5564 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
5565 p2pMode = "CLI";
5566 }
5567 break;
5568 case WLAN_HDD_P2P_GO:
5569 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
5570 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5571 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
5572 p2pChannel = pHddApCtx->operatingChannel;
5573 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
5574 }
5575 p2pMode = "GO";
5576 break;
5577 case WLAN_HDD_SOFTAP:
5578 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
5579 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5580 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
5581 apChannel = pHddApCtx->operatingChannel;
5582 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
5583 }
5584 break;
5585 default:
5586 break;
5587 }
5588 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5589 pAdapterNode = pNext;
5590 }
5591 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
5592 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
5593 }
5594 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
5595 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
5596 if (p2pChannel > 0) {
5597 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
5598 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
5599 }
5600 if (apChannel > 0) {
5601 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
5602 apChannel, MAC_ADDR_ARRAY(apBssid));
5603 }
5604
5605 if (p2pChannel > 0 && apChannel > 0) {
5606 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
5607 }
5608}
5609
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005610bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005611{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005612 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07005613}
5614
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005615/* Once SSR is disabled then it cannot be set. */
5616void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07005617{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005618 if (HDD_SSR_DISABLED == isSsrRequired)
5619 return;
5620
Jeff Johnson295189b2012-06-20 16:38:30 -07005621 isSsrRequired = value;
5622}
5623
5624VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
5625 hdd_adapter_list_node_t** ppAdapterNode)
5626{
5627 VOS_STATUS status;
5628 spin_lock(&pHddCtx->hddAdapters.lock);
5629 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
5630 (hdd_list_node_t**) ppAdapterNode );
5631 spin_unlock(&pHddCtx->hddAdapters.lock);
5632 return status;
5633}
5634
5635VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
5636 hdd_adapter_list_node_t* pAdapterNode,
5637 hdd_adapter_list_node_t** pNextAdapterNode)
5638{
5639 VOS_STATUS status;
5640 spin_lock(&pHddCtx->hddAdapters.lock);
5641 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
5642 (hdd_list_node_t*) pAdapterNode,
5643 (hdd_list_node_t**)pNextAdapterNode );
5644
5645 spin_unlock(&pHddCtx->hddAdapters.lock);
5646 return status;
5647}
5648
5649VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
5650 hdd_adapter_list_node_t* pAdapterNode)
5651{
5652 VOS_STATUS status;
5653 spin_lock(&pHddCtx->hddAdapters.lock);
5654 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
5655 &pAdapterNode->node );
5656 spin_unlock(&pHddCtx->hddAdapters.lock);
5657 return status;
5658}
5659
5660VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
5661 hdd_adapter_list_node_t** ppAdapterNode)
5662{
5663 VOS_STATUS status;
5664 spin_lock(&pHddCtx->hddAdapters.lock);
5665 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
5666 (hdd_list_node_t**) ppAdapterNode );
5667 spin_unlock(&pHddCtx->hddAdapters.lock);
5668 return status;
5669}
5670
5671VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
5672 hdd_adapter_list_node_t* pAdapterNode)
5673{
5674 VOS_STATUS status;
5675 spin_lock(&pHddCtx->hddAdapters.lock);
5676 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
5677 (hdd_list_node_t*) pAdapterNode );
5678 spin_unlock(&pHddCtx->hddAdapters.lock);
5679 return status;
5680}
5681
5682VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
5683 hdd_adapter_list_node_t* pAdapterNode)
5684{
5685 VOS_STATUS status;
5686 spin_lock(&pHddCtx->hddAdapters.lock);
5687 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
5688 (hdd_list_node_t*) pAdapterNode );
5689 spin_unlock(&pHddCtx->hddAdapters.lock);
5690 return status;
5691}
5692
5693hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
5694 tSirMacAddr macAddr )
5695{
5696 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5697 hdd_adapter_t *pAdapter;
5698 VOS_STATUS status;
5699
5700 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5701
5702 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5703 {
5704 pAdapter = pAdapterNode->pAdapter;
5705
5706 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
5707 macAddr, sizeof(tSirMacAddr) ) )
5708 {
5709 return pAdapter;
5710 }
5711 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5712 pAdapterNode = pNext;
5713 }
5714
5715 return NULL;
5716
5717}
5718
5719hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
5720{
5721 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5722 hdd_adapter_t *pAdapter;
5723 VOS_STATUS status;
5724
5725 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5726
5727 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5728 {
5729 pAdapter = pAdapterNode->pAdapter;
5730
5731 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
5732 IFNAMSIZ ) )
5733 {
5734 return pAdapter;
5735 }
5736 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5737 pAdapterNode = pNext;
5738 }
5739
5740 return NULL;
5741
5742}
5743
5744hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
5745{
5746 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5747 hdd_adapter_t *pAdapter;
5748 VOS_STATUS status;
5749
5750 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5751
5752 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5753 {
5754 pAdapter = pAdapterNode->pAdapter;
5755
5756 if( pAdapter && (mode == pAdapter->device_mode) )
5757 {
5758 return pAdapter;
5759 }
5760 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5761 pAdapterNode = pNext;
5762 }
5763
5764 return NULL;
5765
5766}
5767
5768//Remove this function later
5769hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
5770{
5771 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5772 hdd_adapter_t *pAdapter;
5773 VOS_STATUS status;
5774
5775 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5776
5777 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5778 {
5779 pAdapter = pAdapterNode->pAdapter;
5780
5781 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
5782 {
5783 return pAdapter;
5784 }
5785
5786 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5787 pAdapterNode = pNext;
5788 }
5789
5790 return NULL;
5791
5792}
5793
Jeff Johnson295189b2012-06-20 16:38:30 -07005794/**---------------------------------------------------------------------------
5795
5796 \brief hdd_set_monitor_tx_adapter() -
5797
5798 This API initializes the adapter to be used while transmitting on monitor
5799 adapter.
5800
5801 \param - pHddCtx - Pointer to the HDD context.
5802 pAdapter - Adapter that will used for TX. This can be NULL.
5803 \return - None.
5804 --------------------------------------------------------------------------*/
5805void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5806{
5807 hdd_adapter_t *pMonAdapter;
5808
5809 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
5810
5811 if( NULL != pMonAdapter )
5812 {
5813 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
5814 }
5815}
Jeff Johnson295189b2012-06-20 16:38:30 -07005816/**---------------------------------------------------------------------------
5817
5818 \brief hdd_select_queue() -
5819
5820 This API returns the operating channel of the requested device mode
5821
5822 \param - pHddCtx - Pointer to the HDD context.
5823 - mode - Device mode for which operating channel is required
5824 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
5825 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
5826 \return - channel number. "0" id the requested device is not found OR it is not connected.
5827 --------------------------------------------------------------------------*/
5828v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
5829{
5830 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5831 VOS_STATUS status;
5832 hdd_adapter_t *pAdapter;
5833 v_U8_t operatingChannel = 0;
5834
5835 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5836
5837 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5838 {
5839 pAdapter = pAdapterNode->pAdapter;
5840
5841 if( mode == pAdapter->device_mode )
5842 {
5843 switch(pAdapter->device_mode)
5844 {
5845 case WLAN_HDD_INFRA_STATION:
5846 case WLAN_HDD_P2P_CLIENT:
5847 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5848 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
5849 break;
5850 case WLAN_HDD_SOFTAP:
5851 case WLAN_HDD_P2P_GO:
5852 /*softap connection info */
5853 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5854 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
5855 break;
5856 default:
5857 break;
5858 }
5859
5860 break; //Found the device of interest. break the loop
5861 }
5862
5863 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5864 pAdapterNode = pNext;
5865 }
5866 return operatingChannel;
5867}
5868
5869#ifdef WLAN_FEATURE_PACKET_FILTERING
5870/**---------------------------------------------------------------------------
5871
5872 \brief hdd_set_multicast_list() -
5873
5874 This used to set the multicast address list.
5875
5876 \param - dev - Pointer to the WLAN device.
5877 - skb - Pointer to OS packet (sk_buff).
5878 \return - success/fail
5879
5880 --------------------------------------------------------------------------*/
5881static void hdd_set_multicast_list(struct net_device *dev)
5882{
5883 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005884 int mc_count;
5885 int i = 0;
5886 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05305887
5888 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07005889 {
5890 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05305891 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005892 return;
5893 }
5894
5895 if (dev->flags & IFF_ALLMULTI)
5896 {
5897 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005898 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05305899 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005900 }
5901 else
5902 {
5903 mc_count = netdev_mc_count(dev);
5904 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005905 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07005906 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
5907 {
5908 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005909 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05305910 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005911 return;
5912 }
5913
Gopichand Nakkala0f276812013-02-24 14:45:51 +05305914 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07005915
5916 netdev_for_each_mc_addr(ha, dev) {
5917 if (i == mc_count)
5918 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05305919 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
5920 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
5921 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005922 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05305923 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07005924 i++;
5925 }
5926 }
5927 return;
5928}
5929#endif
5930
5931/**---------------------------------------------------------------------------
5932
5933 \brief hdd_select_queue() -
5934
5935 This function is registered with the Linux OS for network
5936 core to decide which queue to use first.
5937
5938 \param - dev - Pointer to the WLAN device.
5939 - skb - Pointer to OS packet (sk_buff).
5940 \return - ac, Queue Index/access category corresponding to UP in IP header
5941
5942 --------------------------------------------------------------------------*/
5943v_U16_t hdd_select_queue(struct net_device *dev,
5944 struct sk_buff *skb)
5945{
5946 return hdd_wmm_select_queue(dev, skb);
5947}
5948
5949
5950/**---------------------------------------------------------------------------
5951
5952 \brief hdd_wlan_initial_scan() -
5953
5954 This function triggers the initial scan
5955
5956 \param - pAdapter - Pointer to the HDD adapter.
5957
5958 --------------------------------------------------------------------------*/
5959void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
5960{
5961 tCsrScanRequest scanReq;
5962 tCsrChannelInfo channelInfo;
5963 eHalStatus halStatus;
5964 unsigned long scanId;
5965 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5966
5967 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
5968 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
5969 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
5970
5971 if(sme_Is11dSupported(pHddCtx->hHal))
5972 {
5973 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
5974 if ( HAL_STATUS_SUCCESS( halStatus ) )
5975 {
5976 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
5977 if( !scanReq.ChannelInfo.ChannelList )
5978 {
5979 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
5980 vos_mem_free(channelInfo.ChannelList);
5981 return;
5982 }
5983 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
5984 channelInfo.numOfChannels);
5985 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
5986 vos_mem_free(channelInfo.ChannelList);
5987 }
5988
5989 scanReq.scanType = eSIR_PASSIVE_SCAN;
5990 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
5991 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
5992 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
5993 }
5994 else
5995 {
5996 scanReq.scanType = eSIR_ACTIVE_SCAN;
5997 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
5998 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
5999 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6000 }
6001
6002 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6003 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6004 {
6005 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6006 __func__, halStatus );
6007 }
6008
6009 if(sme_Is11dSupported(pHddCtx->hHal))
6010 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6011}
6012
6013struct fullPowerContext
6014{
6015 struct completion completion;
6016 unsigned int magic;
6017};
6018#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6019
6020/**---------------------------------------------------------------------------
6021
6022 \brief hdd_full_power_callback() - HDD full power callback function
6023
6024 This is the function invoked by SME to inform the result of a full power
6025 request issued by HDD
6026
6027 \param - callbackcontext - Pointer to cookie
6028 \param - status - result of request
6029
6030 \return - None
6031
6032 --------------------------------------------------------------------------*/
6033static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6034{
6035 struct fullPowerContext *pContext = callbackContext;
6036
6037 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306038 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006039
6040 if (NULL == callbackContext)
6041 {
6042 hddLog(VOS_TRACE_LEVEL_ERROR,
6043 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006044 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006045 return;
6046 }
6047
6048 /* there is a race condition that exists between this callback function
6049 and the caller since the caller could time out either before or
6050 while this code is executing. we'll assume the timeout hasn't
6051 occurred, but we'll verify that right before we save our work */
6052
6053 if (POWER_CONTEXT_MAGIC != pContext->magic)
6054 {
6055 /* the caller presumably timed out so there is nothing we can do */
6056 hddLog(VOS_TRACE_LEVEL_WARN,
6057 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006058 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006059 return;
6060 }
6061
6062 /* the race is on. caller could have timed out immediately after
6063 we verified the magic, but if so, caller will wait a short time
6064 for us to notify the caller, so the context will stay valid */
6065 complete(&pContext->completion);
6066}
6067
6068/**---------------------------------------------------------------------------
6069
6070 \brief hdd_wlan_exit() - HDD WLAN exit function
6071
6072 This is the driver exit point (invoked during rmmod)
6073
6074 \param - pHddCtx - Pointer to the HDD Context
6075
6076 \return - None
6077
6078 --------------------------------------------------------------------------*/
6079void hdd_wlan_exit(hdd_context_t *pHddCtx)
6080{
6081 eHalStatus halStatus;
6082 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6083 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306084 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006085 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006086 struct fullPowerContext powerContext;
6087 long lrc;
6088
6089 ENTER();
6090
Jeff Johnson88ba7742013-02-27 14:36:02 -08006091 if (VOS_FTM_MODE != hdd_get_conparam())
6092 {
6093 // Unloading, restart logic is no more required.
6094 wlan_hdd_restart_deinit(pHddCtx);
6095 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006096
Jeff Johnson295189b2012-06-20 16:38:30 -07006097 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006098 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006099 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006100 {
6101 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6102 WLAN_HDD_INFRA_STATION);
6103 if (pAdapter == NULL)
6104 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6105
6106 if (pAdapter != NULL)
6107 {
6108 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6109 hdd_UnregisterWext(pAdapter->dev);
6110 }
6111 }
6112 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006113
Jeff Johnson295189b2012-06-20 16:38:30 -07006114 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006115 {
6116 wlan_hdd_ftm_close(pHddCtx);
6117 goto free_hdd_ctx;
6118 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006119 //Stop the Interface TX queue.
6120 //netif_tx_disable(pWlanDev);
6121 //netif_carrier_off(pWlanDev);
6122
Jeff Johnson295189b2012-06-20 16:38:30 -07006123 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6124 {
6125 pAdapter = hdd_get_adapter(pHddCtx,
6126 WLAN_HDD_SOFTAP);
6127 }
6128 else
6129 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006130 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006131 {
6132 pAdapter = hdd_get_adapter(pHddCtx,
6133 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006134 if (pAdapter == NULL)
6135 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006136 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006137 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006138 /* DeRegister with platform driver as client for Suspend/Resume */
6139 vosStatus = hddDeregisterPmOps(pHddCtx);
6140 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6141 {
6142 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6143 VOS_ASSERT(0);
6144 }
6145
6146 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6147 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6148 {
6149 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6150 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006151
6152 // Cancel any outstanding scan requests. We are about to close all
6153 // of our adapters, but an adapter structure is what SME passes back
6154 // to our callback function. Hence if there are any outstanding scan
6155 // requests then there is a race condition between when the adapter
6156 // is closed and when the callback is invoked. We try to resolve that
6157 // race condition here by canceling any outstanding scans before we
6158 // close the adapters.
6159 // Note that the scans may be cancelled in an asynchronous manner, so
6160 // ideally there needs to be some kind of synchronization. Rather than
6161 // introduce a new synchronization here, we will utilize the fact that
6162 // we are about to Request Full Power, and since that is synchronized,
6163 // the expectation is that by the time Request Full Power has completed,
6164 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006165 if (NULL != pAdapter)
6166 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6167 else
6168 hddLog(VOS_TRACE_LEVEL_ERROR,
6169 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006170
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006171 //Stop the traffic monitor timer
6172 if ( VOS_TIMER_STATE_RUNNING ==
6173 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6174 {
6175 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6176 }
6177
6178 // Destroy the traffic monitor timer
6179 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
6180 &pHddCtx->tx_rx_trafficTmr)))
6181 {
6182 hddLog(VOS_TRACE_LEVEL_ERROR,
6183 "%s: Cannot deallocate Traffic monitor timer", __func__);
6184 }
6185
Jeff Johnson295189b2012-06-20 16:38:30 -07006186 //Disable IMPS/BMPS as we do not want the device to enter any power
6187 //save mode during shutdown
6188 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6189 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6190 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
6191
6192 //Ensure that device is in full power as we will touch H/W during vos_Stop
6193 init_completion(&powerContext.completion);
6194 powerContext.magic = POWER_CONTEXT_MAGIC;
6195
6196 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
6197 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
6198
6199 if (eHAL_STATUS_SUCCESS != halStatus)
6200 {
6201 if (eHAL_STATUS_PMC_PENDING == halStatus)
6202 {
6203 /* request was sent -- wait for the response */
6204 lrc = wait_for_completion_interruptible_timeout(
6205 &powerContext.completion,
6206 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
6207 /* either we have a response or we timed out
6208 either way, first invalidate our magic */
6209 powerContext.magic = 0;
6210 if (lrc <= 0)
6211 {
6212 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006213 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07006214 /* there is a race condition such that the callback
6215 function could be executing at the same time we are. of
6216 primary concern is if the callback function had already
6217 verified the "magic" but hasn't yet set the completion
6218 variable. Since the completion variable is on our
6219 stack, we'll delay just a bit to make sure the data is
6220 still valid if that is the case */
6221 msleep(50);
6222 }
6223 }
6224 else
6225 {
6226 hddLog(VOS_TRACE_LEVEL_ERROR,
6227 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006228 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07006229 VOS_ASSERT(0);
6230 /* continue -- need to clean up as much as possible */
6231 }
6232 }
6233
Yue Ma0d4891e2013-08-06 17:01:45 -07006234 hdd_debugfs_exit(pHddCtx);
6235
Jeff Johnson295189b2012-06-20 16:38:30 -07006236 // Unregister the Net Device Notifier
6237 unregister_netdevice_notifier(&hdd_netdev_notifier);
6238
Jeff Johnson295189b2012-06-20 16:38:30 -07006239 hdd_stop_all_adapters( pHddCtx );
6240
Jeff Johnson295189b2012-06-20 16:38:30 -07006241#ifdef WLAN_BTAMP_FEATURE
6242 vosStatus = WLANBAP_Stop(pVosContext);
6243 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6244 {
6245 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
6246 "%s: Failed to stop BAP",__func__);
6247 }
6248#endif //WLAN_BTAMP_FEATURE
6249
6250 //Stop all the modules
6251 vosStatus = vos_stop( pVosContext );
6252 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6253 {
6254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6255 "%s: Failed to stop VOSS",__func__);
6256 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6257 }
6258
Jeff Johnson295189b2012-06-20 16:38:30 -07006259 //Assert Deep sleep signal now to put Libra HW in lowest power state
6260 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6261 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6262
6263 //Vote off any PMIC voltage supplies
6264 vos_chipPowerDown(NULL, NULL, NULL);
6265
6266 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
6267
Leo Chang59cdc7e2013-07-10 10:08:21 -07006268
Jeff Johnson295189b2012-06-20 16:38:30 -07006269 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07006270 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006271
6272 //Close the scheduler before calling vos_close to make sure no thread is
6273 // scheduled after the each module close is called i.e after all the data
6274 // structures are freed.
6275 vosStatus = vos_sched_close( pVosContext );
6276 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
6277 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6278 "%s: Failed to close VOSS Scheduler",__func__);
6279 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6280 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006281#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006282#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6283 /* Destroy the wake lock */
6284 wake_lock_destroy(&pHddCtx->rx_wake_lock);
6285#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006286 /* Destroy the wake lock */
6287 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006288#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006289
6290 //Close VOSS
6291 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
6292 vos_close(pVosContext);
6293
Jeff Johnson295189b2012-06-20 16:38:30 -07006294 //Close Watchdog
6295 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6296 vos_watchdog_close(pVosContext);
6297
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306298 //Clean up HDD Nlink Service
6299 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07006300#ifdef WLAN_KD_READY_NOTIFIER
6301 nl_srv_exit(pHddCtx->ptt_pid);
6302#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306303 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006304#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306305
Jeff Johnson295189b2012-06-20 16:38:30 -07006306 /* Cancel the vote for XO Core ON.
6307 * This is done here to ensure there is no race condition since MC, TX and WD threads have
6308 * exited at this point
6309 */
6310 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
6311 " when WLAN is turned OFF\n");
6312 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6313 {
6314 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
6315 " Not returning failure."
6316 " Power consumed will be high\n");
6317 }
6318
6319 hdd_close_all_adapters( pHddCtx );
6320
6321
6322 //Free up dynamically allocated members inside HDD Adapter
6323 kfree(pHddCtx->cfg_ini);
6324 pHddCtx->cfg_ini= NULL;
6325
6326 /* free the power on lock from platform driver */
6327 if (free_riva_power_on_lock("wlan"))
6328 {
6329 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
6330 __func__);
6331 }
6332
Jeff Johnson88ba7742013-02-27 14:36:02 -08006333free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07006334 /* FTM mode, WIPHY did not registered
6335 If un-register here, system crash will happen */
6336 if (VOS_FTM_MODE != hdd_get_conparam())
6337 {
6338 wiphy_unregister(wiphy) ;
6339 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006340 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006341 if (hdd_is_ssr_required())
6342 {
6343 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07006344 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07006345 msleep(5000);
6346 }
6347 hdd_set_ssr_required (VOS_FALSE);
6348}
6349
6350
6351/**---------------------------------------------------------------------------
6352
6353 \brief hdd_update_config_from_nv() - Function to update the contents of
6354 the running configuration with parameters taken from NV storage
6355
6356 \param - pHddCtx - Pointer to the HDD global context
6357
6358 \return - VOS_STATUS_SUCCESS if successful
6359
6360 --------------------------------------------------------------------------*/
6361static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
6362{
Jeff Johnson295189b2012-06-20 16:38:30 -07006363 v_BOOL_t itemIsValid = VOS_FALSE;
6364 VOS_STATUS status;
6365 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
6366 v_U8_t macLoop;
6367
6368 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
6369 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
6370 if(status != VOS_STATUS_SUCCESS)
6371 {
6372 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
6373 return VOS_STATUS_E_FAILURE;
6374 }
6375
6376 if (itemIsValid == VOS_TRUE)
6377 {
6378 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
6379 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
6380 VOS_MAX_CONCURRENCY_PERSONA);
6381 if(status != VOS_STATUS_SUCCESS)
6382 {
6383 /* Get MAC from NV fail, not update CFG info
6384 * INI MAC value will be used for MAC setting */
6385 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
6386 return VOS_STATUS_E_FAILURE;
6387 }
6388
6389 /* If first MAC is not valid, treat all others are not valid
6390 * Then all MACs will be got from ini file */
6391 if(vos_is_macaddr_zero(&macFromNV[0]))
6392 {
6393 /* MAC address in NV file is not configured yet */
6394 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
6395 return VOS_STATUS_E_INVAL;
6396 }
6397
6398 /* Get MAC address from NV, update CFG info */
6399 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
6400 {
6401 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
6402 {
6403 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
6404 /* This MAC is not valid, skip it
6405 * This MAC will be got from ini file */
6406 }
6407 else
6408 {
6409 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
6410 (v_U8_t *)&macFromNV[macLoop].bytes[0],
6411 VOS_MAC_ADDR_SIZE);
6412 }
6413 }
6414 }
6415 else
6416 {
6417 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
6418 return VOS_STATUS_E_FAILURE;
6419 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006420
Jeff Johnson295189b2012-06-20 16:38:30 -07006421
6422 return VOS_STATUS_SUCCESS;
6423}
6424
6425/**---------------------------------------------------------------------------
6426
6427 \brief hdd_post_voss_start_config() - HDD post voss start config helper
6428
6429 \param - pAdapter - Pointer to the HDD
6430
6431 \return - None
6432
6433 --------------------------------------------------------------------------*/
6434VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
6435{
6436 eHalStatus halStatus;
6437 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306438 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07006439
Jeff Johnson295189b2012-06-20 16:38:30 -07006440
6441 // Send ready indication to the HDD. This will kick off the MAC
6442 // into a 'running' state and should kick off an initial scan.
6443 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
6444 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6445 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306446 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07006447 "code %08d [x%08x]",__func__, halStatus, halStatus );
6448 return VOS_STATUS_E_FAILURE;
6449 }
6450
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306451 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07006452 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
6453 // And RIVA will crash
6454 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
6455 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306456 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
6457 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
6458
6459
Jeff Johnson295189b2012-06-20 16:38:30 -07006460 return VOS_STATUS_SUCCESS;
6461}
6462
Jeff Johnson295189b2012-06-20 16:38:30 -07006463/* wake lock APIs for HDD */
6464void hdd_prevent_suspend(void)
6465{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006466#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006467 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006468#else
6469 wcnss_prevent_suspend();
6470#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006471}
6472
6473void hdd_allow_suspend(void)
6474{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006475#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006476 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006477#else
6478 wcnss_allow_suspend();
6479#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006480}
6481
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07006482void hdd_allow_suspend_timeout(v_U32_t timeout)
6483{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006484#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07006485 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07006486#else
6487 /* Do nothing as there is no API in wcnss for timeout*/
6488#endif
6489}
6490
Jeff Johnson295189b2012-06-20 16:38:30 -07006491/**---------------------------------------------------------------------------
6492
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006493 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
6494 information between Host and Riva
6495
6496 This function gets reported version of FW
6497 It also finds the version of Riva headers used to compile the host
6498 It compares the above two and prints a warning if they are different
6499 It gets the SW and HW version string
6500 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
6501 indicating the features they support through a bitmap
6502
6503 \param - pHddCtx - Pointer to HDD context
6504
6505 \return - void
6506
6507 --------------------------------------------------------------------------*/
6508
6509void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
6510{
6511
6512 tSirVersionType versionCompiled;
6513 tSirVersionType versionReported;
6514 tSirVersionString versionString;
6515 tANI_U8 fwFeatCapsMsgSupported = 0;
6516 VOS_STATUS vstatus;
6517
6518 /* retrieve and display WCNSS version information */
6519 do {
6520
6521 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
6522 &versionCompiled);
6523 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6524 {
6525 hddLog(VOS_TRACE_LEVEL_FATAL,
6526 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006527 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006528 break;
6529 }
6530
6531 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
6532 &versionReported);
6533 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6534 {
6535 hddLog(VOS_TRACE_LEVEL_FATAL,
6536 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006537 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006538 break;
6539 }
6540
6541 if ((versionCompiled.major != versionReported.major) ||
6542 (versionCompiled.minor != versionReported.minor) ||
6543 (versionCompiled.version != versionReported.version) ||
6544 (versionCompiled.revision != versionReported.revision))
6545 {
6546 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
6547 "Host expected %u.%u.%u.%u\n",
6548 WLAN_MODULE_NAME,
6549 (int)versionReported.major,
6550 (int)versionReported.minor,
6551 (int)versionReported.version,
6552 (int)versionReported.revision,
6553 (int)versionCompiled.major,
6554 (int)versionCompiled.minor,
6555 (int)versionCompiled.version,
6556 (int)versionCompiled.revision);
6557 }
6558 else
6559 {
6560 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
6561 WLAN_MODULE_NAME,
6562 (int)versionReported.major,
6563 (int)versionReported.minor,
6564 (int)versionReported.version,
6565 (int)versionReported.revision);
6566 }
6567
6568 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
6569 versionString,
6570 sizeof(versionString));
6571 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6572 {
6573 hddLog(VOS_TRACE_LEVEL_FATAL,
6574 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006575 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006576 break;
6577 }
6578
6579 pr_info("%s: WCNSS software version %s\n",
6580 WLAN_MODULE_NAME, versionString);
6581
6582 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
6583 versionString,
6584 sizeof(versionString));
6585 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6586 {
6587 hddLog(VOS_TRACE_LEVEL_FATAL,
6588 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006589 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006590 break;
6591 }
6592
6593 pr_info("%s: WCNSS hardware version %s\n",
6594 WLAN_MODULE_NAME, versionString);
6595
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006596 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
6597 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006598 send the message only if it the riva is 1.1
6599 minor numbers for different riva branches:
6600 0 -> (1.0)Mainline Build
6601 1 -> (1.1)Mainline Build
6602 2->(1.04) Stability Build
6603 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006604 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006605 ((versionReported.minor>=1) && (versionReported.version>=1)))
6606 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
6607 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006608
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006609 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08006610 {
6611#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6612 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
6613 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
6614#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07006615 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
6616 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
6617 {
6618 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
6619 }
6620
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006621 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08006622 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006623
6624 } while (0);
6625
6626}
6627
6628/**---------------------------------------------------------------------------
6629
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05306630 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
6631
6632 \param - pHddCtx - Pointer to the hdd context
6633
6634 \return - true if hardware supports 5GHz
6635
6636 --------------------------------------------------------------------------*/
6637static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
6638{
6639 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
6640 * then hardware support 5Ghz.
6641 */
6642 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
6643 {
6644 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
6645 return true;
6646 }
6647 else
6648 {
6649 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
6650 __func__);
6651 return false;
6652 }
6653}
6654
6655
6656/**---------------------------------------------------------------------------
6657
Jeff Johnson295189b2012-06-20 16:38:30 -07006658 \brief hdd_wlan_startup() - HDD init function
6659
6660 This is the driver startup code executed once a WLAN device has been detected
6661
6662 \param - dev - Pointer to the underlying device
6663
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006664 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07006665
6666 --------------------------------------------------------------------------*/
6667
6668int hdd_wlan_startup(struct device *dev )
6669{
6670 VOS_STATUS status;
6671 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07006672 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006673 hdd_context_t *pHddCtx = NULL;
6674 v_CONTEXT_t pVosContext= NULL;
6675#ifdef WLAN_BTAMP_FEATURE
6676 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
6677 WLANBAP_ConfigType btAmpConfig;
6678 hdd_config_t *pConfig;
6679#endif
6680 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006681 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006682
6683 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006684 /*
6685 * cfg80211: wiphy allocation
6686 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306687 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006688
6689 if(wiphy == NULL)
6690 {
6691 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006692 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006693 }
6694
6695 pHddCtx = wiphy_priv(wiphy);
6696
Jeff Johnson295189b2012-06-20 16:38:30 -07006697 //Initialize the adapter context to zeros.
6698 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
6699
Jeff Johnson295189b2012-06-20 16:38:30 -07006700 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006701 hdd_prevent_suspend();
6702 pHddCtx->isLoadUnloadInProgress = TRUE;
6703
6704 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6705
6706 /*Get vos context here bcoz vos_open requires it*/
6707 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6708
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08006709 if(pVosContext == NULL)
6710 {
6711 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
6712 goto err_free_hdd_context;
6713 }
6714
Jeff Johnson295189b2012-06-20 16:38:30 -07006715 //Save the Global VOSS context in adapter context for future.
6716 pHddCtx->pvosContext = pVosContext;
6717
6718 //Save the adapter context in global context for future.
6719 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
6720
Jeff Johnson295189b2012-06-20 16:38:30 -07006721 pHddCtx->parent_dev = dev;
6722
6723 init_completion(&pHddCtx->full_pwr_comp_var);
6724 init_completion(&pHddCtx->standby_comp_var);
6725 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006726 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08006727 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07006728
6729#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07006730 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07006731#else
6732 init_completion(&pHddCtx->driver_crda_req);
6733#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006734
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05306735 spin_lock_init(&pHddCtx->schedScan_lock);
6736
Jeff Johnson295189b2012-06-20 16:38:30 -07006737 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
6738
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306739#ifdef FEATURE_WLAN_TDLS
6740 /* tdls_lock is initialized before an hdd_open_adapter ( which is
6741 * invoked by other instances also) to protect the concurrent
6742 * access for the Adapters by TDLS module.
6743 */
6744 mutex_init(&pHddCtx->tdls_lock);
6745#endif
6746
Jeff Johnson295189b2012-06-20 16:38:30 -07006747 // Load all config first as TL config is needed during vos_open
6748 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
6749 if(pHddCtx->cfg_ini == NULL)
6750 {
6751 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
6752 goto err_free_hdd_context;
6753 }
6754
6755 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
6756
6757 // Read and parse the qcom_cfg.ini file
6758 status = hdd_parse_config_ini( pHddCtx );
6759 if ( VOS_STATUS_SUCCESS != status )
6760 {
6761 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
6762 __func__, WLAN_INI_FILE);
6763 goto err_config;
6764 }
6765
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05306766 /* INI has been read, initialise the configuredMcastBcastFilter with
6767 * INI value as this will serve as the default value
6768 */
6769 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
6770 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
6771 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05306772
6773 if (false == hdd_is_5g_supported(pHddCtx))
6774 {
6775 //5Ghz is not supported.
6776 if (1 != pHddCtx->cfg_ini->nBandCapability)
6777 {
6778 hddLog(VOS_TRACE_LEVEL_INFO,
6779 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
6780 pHddCtx->cfg_ini->nBandCapability = 1;
6781 }
6782 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05306783
6784 /* If SNR Monitoring is enabled, FW has to parse all beacons
6785 * for calcaluting and storing the average SNR, so set Nth beacon
6786 * filter to 1 to enable FW to parse all the beaocons
6787 */
6788 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
6789 {
6790 /* The log level is deliberately set to WARN as overriding
6791 * nthBeaconFilter to 1 will increase power cosumption and this
6792 * might just prove helpful to detect the power issue.
6793 */
6794 hddLog(VOS_TRACE_LEVEL_WARN,
6795 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
6796 pHddCtx->cfg_ini->nthBeaconFilter = 1;
6797 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006798 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306799 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07006800 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306801 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07006802 {
6803 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306804 "%s: wlan_hdd_cfg80211_init return failure", __func__);
6805 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07006806 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006807
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006808 // Update VOS trace levels based upon the cfg.ini
6809 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
6810 pHddCtx->cfg_ini->vosTraceEnableBAP);
6811 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
6812 pHddCtx->cfg_ini->vosTraceEnableTL);
6813 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
6814 pHddCtx->cfg_ini->vosTraceEnableWDI);
6815 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
6816 pHddCtx->cfg_ini->vosTraceEnableHDD);
6817 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
6818 pHddCtx->cfg_ini->vosTraceEnableSME);
6819 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
6820 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05306821 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
6822 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006823 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
6824 pHddCtx->cfg_ini->vosTraceEnableWDA);
6825 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
6826 pHddCtx->cfg_ini->vosTraceEnableSYS);
6827 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
6828 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006829 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
6830 pHddCtx->cfg_ini->vosTraceEnableSAP);
6831 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
6832 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006833
Jeff Johnson295189b2012-06-20 16:38:30 -07006834 // Update WDI trace levels based upon the cfg.ini
6835 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
6836 pHddCtx->cfg_ini->wdiTraceEnableDAL);
6837 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
6838 pHddCtx->cfg_ini->wdiTraceEnableCTL);
6839 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
6840 pHddCtx->cfg_ini->wdiTraceEnableDAT);
6841 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
6842 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006843
Jeff Johnson88ba7742013-02-27 14:36:02 -08006844 if (VOS_FTM_MODE == hdd_get_conparam())
6845 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006846 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
6847 {
6848 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
6849 goto err_free_hdd_context;
6850 }
6851 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
6852 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08006853 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006854
Jeff Johnson88ba7742013-02-27 14:36:02 -08006855 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07006856 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6857 {
6858 status = vos_watchdog_open(pVosContext,
6859 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
6860
6861 if(!VOS_IS_STATUS_SUCCESS( status ))
6862 {
6863 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306864 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07006865 }
6866 }
6867
6868 pHddCtx->isLogpInProgress = FALSE;
6869 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
6870
Jeff Johnson295189b2012-06-20 16:38:30 -07006871 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
6872 if(!VOS_IS_STATUS_SUCCESS(status))
6873 {
6874 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006875 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07006876 }
6877
Amar Singhala49cbc52013-10-08 18:37:44 -07006878#ifdef CONFIG_ENABLE_LINUX_REG
6879 /* registration of wiphy dev with cfg80211 */
6880 if (0 > wlan_hdd_cfg80211_register(wiphy))
6881 {
6882 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
6883 goto err_clkvote;
6884 }
6885#endif
6886
Jeff Johnson295189b2012-06-20 16:38:30 -07006887 status = vos_open( &pVosContext, 0);
6888 if ( !VOS_IS_STATUS_SUCCESS( status ))
6889 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006890 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07006891 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07006892 }
6893
Jeff Johnson295189b2012-06-20 16:38:30 -07006894 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
6895
6896 if ( NULL == pHddCtx->hHal )
6897 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006898 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006899 goto err_vosclose;
6900 }
6901
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006902 status = vos_preStart( pHddCtx->pvosContext );
6903 if ( !VOS_IS_STATUS_SUCCESS( status ) )
6904 {
6905 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
6906 goto err_vosclose;
6907 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006908
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006909 /* Note that the vos_preStart() sequence triggers the cfg download.
6910 The cfg download must occur before we update the SME config
6911 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07006912 status = hdd_set_sme_config( pHddCtx );
6913
6914 if ( VOS_STATUS_SUCCESS != status )
6915 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006916 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
6917 goto err_vosclose;
6918 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006919
6920 //Initialize the WMM module
6921 status = hdd_wmm_init(pHddCtx);
6922 if (!VOS_IS_STATUS_SUCCESS(status))
6923 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006924 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006925 goto err_vosclose;
6926 }
6927
Jeff Johnson295189b2012-06-20 16:38:30 -07006928 /* In the integrated architecture we update the configuration from
6929 the INI file and from NV before vOSS has been started so that
6930 the final contents are available to send down to the cCPU */
6931
6932 // Apply the cfg.ini to cfg.dat
6933 if (FALSE == hdd_update_config_dat(pHddCtx))
6934 {
6935 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
6936 goto err_vosclose;
6937 }
6938
6939 // Apply the NV to cfg.dat
6940 /* Prima Update MAC address only at here */
6941 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
6942 {
6943#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
6944 /* There was not a valid set of MAC Addresses in NV. See if the
6945 default addresses were modified by the cfg.ini settings. If so,
6946 we'll use them, but if not, we'll autogenerate a set of MAC
6947 addresses based upon the device serial number */
6948
6949 static const v_MACADDR_t default_address =
6950 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
6951 unsigned int serialno;
6952 int i;
6953
6954 serialno = wcnss_get_serial_number();
6955 if ((0 != serialno) &&
6956 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
6957 sizeof(default_address))))
6958 {
6959 /* cfg.ini has the default address, invoke autogen logic */
6960
6961 /* MAC address has 3 bytes of OUI so we have a maximum of 3
6962 bytes of the serial number that can be used to generate
6963 the other 3 bytes of the MAC address. Mask off all but
6964 the lower 3 bytes (this will also make sure we don't
6965 overflow in the next step) */
6966 serialno &= 0x00FFFFFF;
6967
6968 /* we need a unique address for each session */
6969 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
6970
6971 /* autogen all addresses */
6972 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
6973 {
6974 /* start with the entire default address */
6975 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
6976 /* then replace the lower 3 bytes */
6977 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
6978 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
6979 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
6980
6981 serialno++;
6982 }
6983
6984 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
6985 MAC_ADDRESS_STR,
6986 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
6987 }
6988 else
6989#endif //WLAN_AUTOGEN_MACADDR_FEATURE
6990 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006991 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006992 "%s: Invalid MAC address in NV, using MAC from ini file "
6993 MAC_ADDRESS_STR, __func__,
6994 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
6995 }
6996 }
6997 {
6998 eHalStatus halStatus;
6999 // Set the MAC Address
7000 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7001 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7002 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7003 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7004
7005 if (!HAL_STATUS_SUCCESS( halStatus ))
7006 {
7007 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7008 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007009 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007010 }
7011 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007012
7013 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7014 Note: Firmware image will be read and downloaded inside vos_start API */
7015 status = vos_start( pHddCtx->pvosContext );
7016 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7017 {
7018 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7019 goto err_vosclose;
7020 }
7021
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007022 /* Exchange capability info between Host and FW and also get versioning info from FW */
7023 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007024
7025 status = hdd_post_voss_start_config( pHddCtx );
7026 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7027 {
7028 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7029 __func__);
7030 goto err_vosstop;
7031 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007032
7033#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307034 wlan_hdd_cfg80211_update_reg_info( wiphy );
7035
7036 /* registration of wiphy dev with cfg80211 */
7037 if (0 > wlan_hdd_cfg80211_register(wiphy))
7038 {
7039 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7040 goto err_vosstop;
7041 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007042#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007043
Jeff Johnson295189b2012-06-20 16:38:30 -07007044 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7045 {
7046 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7047 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7048 }
7049 else
7050 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007051 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7052 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7053 if (pAdapter != NULL)
7054 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307055 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007056 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307057 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7058 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7059 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007060
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307061 /* Generate the P2P Device Address. This consists of the device's
7062 * primary MAC address with the locally administered bit set.
7063 */
7064 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007065 }
7066 else
7067 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307068 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7069 if (p2p_dev_addr != NULL)
7070 {
7071 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7072 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7073 }
7074 else
7075 {
7076 hddLog(VOS_TRACE_LEVEL_FATAL,
7077 "%s: Failed to allocate mac_address for p2p_device",
7078 __func__);
7079 goto err_close_adapter;
7080 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007081 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007082
7083 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7084 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7085 if ( NULL == pP2pAdapter )
7086 {
7087 hddLog(VOS_TRACE_LEVEL_FATAL,
7088 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007089 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007090 goto err_close_adapter;
7091 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007092 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007093 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007094
7095 if( pAdapter == NULL )
7096 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007097 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7098 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007099 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007100
Jeff Johnson295189b2012-06-20 16:38:30 -07007101#ifdef WLAN_BTAMP_FEATURE
7102 vStatus = WLANBAP_Open(pVosContext);
7103 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7104 {
7105 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7106 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007107 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007108 }
7109
7110 vStatus = BSL_Init(pVosContext);
7111 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7112 {
7113 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7114 "%s: Failed to Init BSL",__func__);
7115 goto err_bap_close;
7116 }
7117 vStatus = WLANBAP_Start(pVosContext);
7118 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7119 {
7120 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7121 "%s: Failed to start TL",__func__);
7122 goto err_bap_close;
7123 }
7124
7125 pConfig = pHddCtx->cfg_ini;
7126 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7127 status = WLANBAP_SetConfig(&btAmpConfig);
7128
7129#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007130
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007131#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7132 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7133 {
7134 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7135 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7136 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7137 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7138 }
7139#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007140#ifdef FEATURE_WLAN_SCAN_PNO
7141 /*SME must send channel update configuration to RIVA*/
7142 sme_UpdateChannelConfig(pHddCtx->hHal);
7143#endif
7144
Jeff Johnson295189b2012-06-20 16:38:30 -07007145 /* Register with platform driver as client for Suspend/Resume */
7146 status = hddRegisterPmOps(pHddCtx);
7147 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7148 {
7149 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7150#ifdef WLAN_BTAMP_FEATURE
7151 goto err_bap_stop;
7152#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007153 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007154#endif //WLAN_BTAMP_FEATURE
7155 }
7156
Yue Ma0d4891e2013-08-06 17:01:45 -07007157 /* Open debugfs interface */
7158 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
7159 {
7160 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7161 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07007162 }
7163
Jeff Johnson295189b2012-06-20 16:38:30 -07007164 /* Register TM level change handler function to the platform */
7165 status = hddDevTmRegisterNotifyCallback(pHddCtx);
7166 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7167 {
7168 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
7169 goto err_unregister_pmops;
7170 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007171
7172 /* register for riva power on lock to platform driver */
7173 if (req_riva_power_on_lock("wlan"))
7174 {
7175 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
7176 __func__);
7177 goto err_unregister_pmops;
7178 }
7179
Jeff Johnson295189b2012-06-20 16:38:30 -07007180 // register net device notifier for device change notification
7181 ret = register_netdevice_notifier(&hdd_netdev_notifier);
7182
7183 if(ret < 0)
7184 {
7185 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
7186 goto err_free_power_on_lock;
7187 }
7188
7189 //Initialize the nlink service
7190 if(nl_srv_init() != 0)
7191 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307192 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007193 goto err_reg_netdev;
7194 }
7195
7196 //Initialize the BTC service
7197 if(btc_activate_service(pHddCtx) != 0)
7198 {
7199 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
7200 goto err_nl_srv;
7201 }
7202
7203#ifdef PTT_SOCK_SVC_ENABLE
7204 //Initialize the PTT service
7205 if(ptt_sock_activate_svc(pHddCtx) != 0)
7206 {
7207 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
7208 goto err_nl_srv;
7209 }
7210#endif
7211
Jeff Johnson295189b2012-06-20 16:38:30 -07007212 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007213 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007214 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07007215 /* Action frame registered in one adapter which will
7216 * applicable to all interfaces
7217 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07007218 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007219 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007220
7221 mutex_init(&pHddCtx->sap_lock);
7222
7223 pHddCtx->isLoadUnloadInProgress = FALSE;
7224
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007225#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007226#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7227 /* Initialize the wake lcok */
7228 wake_lock_init(&pHddCtx->rx_wake_lock,
7229 WAKE_LOCK_SUSPEND,
7230 "qcom_rx_wakelock");
7231#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007232 /* Initialize the wake lcok */
7233 wake_lock_init(&pHddCtx->sap_wake_lock,
7234 WAKE_LOCK_SUSPEND,
7235 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007236#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007237
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007238 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
7239 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07007240
7241 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7242 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05307243
Jeff Johnsone7245742012-09-05 17:12:55 -07007244 // Initialize the restart logic
7245 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05307246
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007247 //Register the traffic monitor timer now
7248 if ( pHddCtx->cfg_ini->dynSplitscan)
7249 {
7250 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
7251 VOS_TIMER_TYPE_SW,
7252 hdd_tx_rx_pkt_cnt_stat_timer_handler,
7253 (void *)pHddCtx);
7254 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007255 goto success;
7256
7257err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07007258#ifdef WLAN_KD_READY_NOTIFIER
7259 nl_srv_exit(pHddCtx->ptt_pid);
7260#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007261 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007262#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07007263err_reg_netdev:
7264 unregister_netdevice_notifier(&hdd_netdev_notifier);
7265
7266err_free_power_on_lock:
7267 free_riva_power_on_lock("wlan");
7268
7269err_unregister_pmops:
7270 hddDevTmUnregisterNotifyCallback(pHddCtx);
7271 hddDeregisterPmOps(pHddCtx);
7272
Yue Ma0d4891e2013-08-06 17:01:45 -07007273 hdd_debugfs_exit(pHddCtx);
7274
Jeff Johnson295189b2012-06-20 16:38:30 -07007275#ifdef WLAN_BTAMP_FEATURE
7276err_bap_stop:
7277 WLANBAP_Stop(pVosContext);
7278#endif
7279
7280#ifdef WLAN_BTAMP_FEATURE
7281err_bap_close:
7282 WLANBAP_Close(pVosContext);
7283#endif
7284
Jeff Johnson295189b2012-06-20 16:38:30 -07007285err_close_adapter:
7286 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07007287
7288#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307289 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07007290#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007291
7292err_vosstop:
7293 vos_stop(pVosContext);
7294
Amar Singhala49cbc52013-10-08 18:37:44 -07007295err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07007296 status = vos_sched_close( pVosContext );
7297 if (!VOS_IS_STATUS_SUCCESS(status)) {
7298 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7299 "%s: Failed to close VOSS Scheduler", __func__);
7300 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
7301 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007302 vos_close(pVosContext );
7303
7304err_wiphy_unregister:
7305
7306#ifdef CONFIG_ENABLE_LINUX_REG
7307 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07007308
Jeff Johnson295189b2012-06-20 16:38:30 -07007309err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07007310#endif
7311
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007312 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007313
7314err_wdclose:
7315 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7316 vos_watchdog_close(pVosContext);
7317
Jeff Johnson295189b2012-06-20 16:38:30 -07007318err_config:
7319 kfree(pHddCtx->cfg_ini);
7320 pHddCtx->cfg_ini= NULL;
7321
7322err_free_hdd_context:
7323 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07007324 wiphy_free(wiphy) ;
7325 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007326 VOS_BUG(1);
7327
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08007328 if (hdd_is_ssr_required())
7329 {
7330 /* WDI timeout had happened during load, so SSR is needed here */
7331 subsystem_restart("wcnss");
7332 msleep(5000);
7333 }
7334 hdd_set_ssr_required (VOS_FALSE);
7335
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007336 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007337
7338success:
7339 EXIT();
7340 return 0;
7341}
7342
7343/**---------------------------------------------------------------------------
7344
Jeff Johnson32d95a32012-09-10 13:15:23 -07007345 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07007346
Jeff Johnson32d95a32012-09-10 13:15:23 -07007347 This is the driver entry point - called in different timeline depending
7348 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07007349
7350 \param - None
7351
7352 \return - 0 for success, non zero for failure
7353
7354 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07007355static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007356{
7357 VOS_STATUS status;
7358 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007359 struct device *dev = NULL;
7360 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007361#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7362 int max_retries = 0;
7363#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007364
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307365#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7366 vos_wconn_trace_init();
7367#endif
7368
Jeff Johnson295189b2012-06-20 16:38:30 -07007369 ENTER();
7370
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007371#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007372 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07007373#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007374
7375 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
7376 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
7377
7378 //Power Up Libra WLAN card first if not already powered up
7379 status = vos_chipPowerUp(NULL,NULL,NULL);
7380 if (!VOS_IS_STATUS_SUCCESS(status))
7381 {
7382 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
7383 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307384#ifdef WLAN_OPEN_SOURCE
7385 wake_lock_destroy(&wlan_wake_lock);
7386#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007387 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007388 }
7389
Jeff Johnson295189b2012-06-20 16:38:30 -07007390#ifdef ANI_BUS_TYPE_PCI
7391
7392 dev = wcnss_wlan_get_device();
7393
7394#endif // ANI_BUS_TYPE_PCI
7395
7396#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007397
7398#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7399 /* wait until WCNSS driver downloads NV */
7400 while (!wcnss_device_ready() && 5 >= ++max_retries) {
7401 msleep(1000);
7402 }
7403 if (max_retries >= 5) {
7404 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307405#ifdef WLAN_OPEN_SOURCE
7406 wake_lock_destroy(&wlan_wake_lock);
7407#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007408 return -ENODEV;
7409 }
7410#endif
7411
Jeff Johnson295189b2012-06-20 16:38:30 -07007412 dev = wcnss_wlan_get_device();
7413#endif // ANI_BUS_TYPE_PLATFORM
7414
7415
7416 do {
7417 if (NULL == dev) {
7418 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
7419 ret_status = -1;
7420 break;
7421 }
7422
7423#ifdef MEMORY_DEBUG
7424 vos_mem_init();
7425#endif
7426
7427#ifdef TIMER_MANAGER
7428 vos_timer_manager_init();
7429#endif
7430
7431 /* Preopen VOSS so that it is ready to start at least SAL */
7432 status = vos_preOpen(&pVosContext);
7433
7434 if (!VOS_IS_STATUS_SUCCESS(status))
7435 {
7436 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
7437 ret_status = -1;
7438 break;
7439 }
7440
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007441#ifndef MODULE
7442 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
7443 */
7444 hdd_set_conparam((v_UINT_t)con_mode);
7445#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007446
7447 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007448 if (hdd_wlan_startup(dev))
7449 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007450 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007451 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007452 vos_preClose( &pVosContext );
7453 ret_status = -1;
7454 break;
7455 }
7456
7457 /* Cancel the vote for XO Core ON
7458 * This is done here for safety purposes in case we re-initialize without turning
7459 * it OFF in any error scenario.
7460 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007461 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07007462 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007463 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07007464 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7465 {
7466 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
7467 " Power consumed will be high\n");
7468 }
7469 } while (0);
7470
7471 if (0 != ret_status)
7472 {
7473 //Assert Deep sleep signal now to put Libra HW in lowest power state
7474 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7475 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
7476
7477 //Vote off any PMIC voltage supplies
7478 vos_chipPowerDown(NULL, NULL, NULL);
7479#ifdef TIMER_MANAGER
7480 vos_timer_exit();
7481#endif
7482#ifdef MEMORY_DEBUG
7483 vos_mem_exit();
7484#endif
7485
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007486#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007487 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007488#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007489 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
7490 }
7491 else
7492 {
7493 //Send WLAN UP indication to Nlink Service
7494 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
7495
7496 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07007497 }
7498
7499 EXIT();
7500
7501 return ret_status;
7502}
7503
Jeff Johnson32d95a32012-09-10 13:15:23 -07007504/**---------------------------------------------------------------------------
7505
7506 \brief hdd_module_init() - Init Function
7507
7508 This is the driver entry point (invoked when module is loaded using insmod)
7509
7510 \param - None
7511
7512 \return - 0 for success, non zero for failure
7513
7514 --------------------------------------------------------------------------*/
7515#ifdef MODULE
7516static int __init hdd_module_init ( void)
7517{
7518 return hdd_driver_init();
7519}
Jeff Johnson32d95a32012-09-10 13:15:23 -07007520#else /* #ifdef MODULE */
7521static int __init hdd_module_init ( void)
7522{
7523 /* Driver initialization is delayed to fwpath_changed_handler */
7524 return 0;
7525}
Jeff Johnson32d95a32012-09-10 13:15:23 -07007526#endif /* #ifdef MODULE */
7527
Jeff Johnson295189b2012-06-20 16:38:30 -07007528
7529/**---------------------------------------------------------------------------
7530
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007531 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007532
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007533 This is the driver exit point (invoked when module is unloaded using rmmod
7534 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07007535
7536 \param - None
7537
7538 \return - None
7539
7540 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007541static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007542{
7543 hdd_context_t *pHddCtx = NULL;
7544 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007545 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007546
7547 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
7548
7549 //Get the global vos context
7550 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7551
7552 if(!pVosContext)
7553 {
7554 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
7555 goto done;
7556 }
7557
7558 //Get the HDD context.
7559 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
7560
7561 if(!pHddCtx)
7562 {
7563 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
7564 }
7565 else
7566 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007567 while(isWDresetInProgress()) {
7568 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7569 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007570 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007571
7572 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
7573 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7574 "%s:SSR never completed, fatal error", __func__);
7575 VOS_BUG(0);
7576 }
7577 }
7578
Jeff Johnson295189b2012-06-20 16:38:30 -07007579
7580 pHddCtx->isLoadUnloadInProgress = TRUE;
7581 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7582
7583 //Do all the cleanup before deregistering the driver
7584 hdd_wlan_exit(pHddCtx);
7585 }
7586
Jeff Johnson295189b2012-06-20 16:38:30 -07007587 vos_preClose( &pVosContext );
7588
7589#ifdef TIMER_MANAGER
7590 vos_timer_exit();
7591#endif
7592#ifdef MEMORY_DEBUG
7593 vos_mem_exit();
7594#endif
7595
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307596#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7597 vos_wconn_trace_exit();
7598#endif
7599
Jeff Johnson295189b2012-06-20 16:38:30 -07007600done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007601#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007602 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007603#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007604 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
7605}
7606
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007607/**---------------------------------------------------------------------------
7608
7609 \brief hdd_module_exit() - Exit function
7610
7611 This is the driver exit point (invoked when module is unloaded using rmmod)
7612
7613 \param - None
7614
7615 \return - None
7616
7617 --------------------------------------------------------------------------*/
7618static void __exit hdd_module_exit(void)
7619{
7620 hdd_driver_exit();
7621}
7622
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007623#ifdef MODULE
7624static int fwpath_changed_handler(const char *kmessage,
7625 struct kernel_param *kp)
7626{
Jeff Johnson76052702013-04-16 13:55:05 -07007627 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007628}
7629
7630static int con_mode_handler(const char *kmessage,
7631 struct kernel_param *kp)
7632{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07007633 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007634}
7635#else /* #ifdef MODULE */
7636/**---------------------------------------------------------------------------
7637
Jeff Johnson76052702013-04-16 13:55:05 -07007638 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007639
Jeff Johnson76052702013-04-16 13:55:05 -07007640 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007641 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07007642 - invoked when module parameter fwpath is modified from userspace to signal
7643 initializing the WLAN driver or when con_mode is modified from userspace
7644 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007645
7646 \return - 0 for success, non zero for failure
7647
7648 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07007649static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007650{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007651 int ret_status;
7652
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007653 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007654 ret_status = hdd_driver_init();
7655 wlan_hdd_inited = ret_status ? 0 : 1;
7656 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007657 }
7658
7659 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07007660
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007661 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07007662
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007663 ret_status = hdd_driver_init();
7664 wlan_hdd_inited = ret_status ? 0 : 1;
7665 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007666}
7667
Jeff Johnson295189b2012-06-20 16:38:30 -07007668/**---------------------------------------------------------------------------
7669
Jeff Johnson76052702013-04-16 13:55:05 -07007670 \brief fwpath_changed_handler() - Handler Function
7671
7672 Handle changes to the fwpath parameter
7673
7674 \return - 0 for success, non zero for failure
7675
7676 --------------------------------------------------------------------------*/
7677static int fwpath_changed_handler(const char *kmessage,
7678 struct kernel_param *kp)
7679{
7680 int ret;
7681
7682 ret = param_set_copystring(kmessage, kp);
7683 if (0 == ret)
7684 ret = kickstart_driver();
7685 return ret;
7686}
7687
7688/**---------------------------------------------------------------------------
7689
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007690 \brief con_mode_handler() -
7691
7692 Handler function for module param con_mode when it is changed by userspace
7693 Dynamically linked - do nothing
7694 Statically linked - exit and init driver, as in rmmod and insmod
7695
Jeff Johnson76052702013-04-16 13:55:05 -07007696 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007697
Jeff Johnson76052702013-04-16 13:55:05 -07007698 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007699
7700 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07007701static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007702{
Jeff Johnson76052702013-04-16 13:55:05 -07007703 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007704
Jeff Johnson76052702013-04-16 13:55:05 -07007705 ret = param_set_int(kmessage, kp);
7706 if (0 == ret)
7707 ret = kickstart_driver();
7708 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007709}
7710#endif /* #ifdef MODULE */
7711
7712/**---------------------------------------------------------------------------
7713
Jeff Johnson295189b2012-06-20 16:38:30 -07007714 \brief hdd_get_conparam() -
7715
7716 This is the driver exit point (invoked when module is unloaded using rmmod)
7717
7718 \param - None
7719
7720 \return - tVOS_CON_MODE
7721
7722 --------------------------------------------------------------------------*/
7723tVOS_CON_MODE hdd_get_conparam ( void )
7724{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007725#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07007726 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007727#else
7728 return (tVOS_CON_MODE)curr_con_mode;
7729#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007730}
7731void hdd_set_conparam ( v_UINT_t newParam )
7732{
7733 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007734#ifndef MODULE
7735 curr_con_mode = con_mode;
7736#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007737}
7738/**---------------------------------------------------------------------------
7739
7740 \brief hdd_softap_sta_deauth() - function
7741
7742 This to take counter measure to handle deauth req from HDD
7743
7744 \param - pAdapter - Pointer to the HDD
7745
7746 \param - enable - boolean value
7747
7748 \return - None
7749
7750 --------------------------------------------------------------------------*/
7751
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007752VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07007753{
Jeff Johnson295189b2012-06-20 16:38:30 -07007754 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007755 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07007756
7757 ENTER();
7758
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007759 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
7760 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007761
7762 //Ignore request to deauth bcmc station
7763 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007764 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07007765
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007766 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07007767
7768 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007769 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07007770}
7771
7772/**---------------------------------------------------------------------------
7773
7774 \brief hdd_softap_sta_disassoc() - function
7775
7776 This to take counter measure to handle deauth req from HDD
7777
7778 \param - pAdapter - Pointer to the HDD
7779
7780 \param - enable - boolean value
7781
7782 \return - None
7783
7784 --------------------------------------------------------------------------*/
7785
7786void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
7787{
7788 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
7789
7790 ENTER();
7791
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307792 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007793
7794 //Ignore request to disassoc bcmc station
7795 if( pDestMacAddress[0] & 0x1 )
7796 return;
7797
7798 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
7799}
7800
7801void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
7802{
7803 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
7804
7805 ENTER();
7806
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307807 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007808
7809 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
7810}
7811
Jeff Johnson295189b2012-06-20 16:38:30 -07007812/**---------------------------------------------------------------------------
7813 *
7814 * \brief hdd_get__concurrency_mode() -
7815 *
7816 *
7817 * \param - None
7818 *
7819 * \return - CONCURRENCY MODE
7820 *
7821 * --------------------------------------------------------------------------*/
7822tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
7823{
7824 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
7825 hdd_context_t *pHddCtx;
7826
7827 if (NULL != pVosContext)
7828 {
7829 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
7830 if (NULL != pHddCtx)
7831 {
7832 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
7833 }
7834 }
7835
7836 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007837 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007838 return VOS_STA;
7839}
7840
7841/* Decide whether to allow/not the apps power collapse.
7842 * Allow apps power collapse if we are in connected state.
7843 * if not, allow only if we are in IMPS */
7844v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
7845{
7846 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08007847 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08007848 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07007849 hdd_config_t *pConfig = pHddCtx->cfg_ini;
7850 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7851 hdd_adapter_t *pAdapter = NULL;
7852 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08007853 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007854
Jeff Johnson295189b2012-06-20 16:38:30 -07007855 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7856 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007857
Yathish9f22e662012-12-10 14:21:35 -08007858 concurrent_state = hdd_get_concurrency_mode();
7859
7860#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7861 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
7862 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
7863 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
7864 return TRUE;
7865#endif
7866
Jeff Johnson295189b2012-06-20 16:38:30 -07007867 /*loop through all adapters. TBD fix for Concurrency */
7868 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7869 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7870 {
7871 pAdapter = pAdapterNode->pAdapter;
7872 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
7873 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7874 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08007875 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07007876 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08007877 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08007878 (eANI_BOOLEAN_TRUE == scanRspPending) ||
7879 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07007880 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08007881 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08007882 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
7883 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07007884 return FALSE;
7885 }
7886 }
7887 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7888 pAdapterNode = pNext;
7889 }
7890 return TRUE;
7891}
7892
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08007893/* Decides whether to send suspend notification to Riva
7894 * if any adapter is in BMPS; then it is required */
7895v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
7896{
7897 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
7898 hdd_config_t *pConfig = pHddCtx->cfg_ini;
7899
7900 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
7901 {
7902 return TRUE;
7903 }
7904 return FALSE;
7905}
7906
Jeff Johnson295189b2012-06-20 16:38:30 -07007907void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
7908{
7909 switch(mode)
7910 {
Chilam Ngc4244af2013-04-01 15:37:32 -07007911 case VOS_STA_MODE:
7912 case VOS_P2P_CLIENT_MODE:
7913 case VOS_P2P_GO_MODE:
7914 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07007915 pHddCtx->concurrency_mode |= (1 << mode);
7916 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07007917 break;
7918 default:
7919 break;
7920
7921 }
7922 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
7923 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
7924}
7925
7926
7927void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
7928{
7929 switch(mode)
7930 {
Chilam Ngc4244af2013-04-01 15:37:32 -07007931 case VOS_STA_MODE:
7932 case VOS_P2P_CLIENT_MODE:
7933 case VOS_P2P_GO_MODE:
7934 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07007935 pHddCtx->no_of_sessions[mode]--;
7936 if (!(pHddCtx->no_of_sessions[mode]))
7937 pHddCtx->concurrency_mode &= (~(1 << mode));
7938 break;
7939 default:
7940 break;
7941 }
7942 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
7943 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
7944}
7945
Jeff Johnsone7245742012-09-05 17:12:55 -07007946/**---------------------------------------------------------------------------
7947 *
7948 * \brief wlan_hdd_restart_init
7949 *
7950 * This function initalizes restart timer/flag. An internal function.
7951 *
7952 * \param - pHddCtx
7953 *
7954 * \return - None
7955 *
7956 * --------------------------------------------------------------------------*/
7957
7958static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
7959{
7960 /* Initialize */
7961 pHddCtx->hdd_restart_retries = 0;
7962 atomic_set(&pHddCtx->isRestartInProgress, 0);
7963 vos_timer_init(&pHddCtx->hdd_restart_timer,
7964 VOS_TIMER_TYPE_SW,
7965 wlan_hdd_restart_timer_cb,
7966 pHddCtx);
7967}
7968/**---------------------------------------------------------------------------
7969 *
7970 * \brief wlan_hdd_restart_deinit
7971 *
7972 * This function cleans up the resources used. An internal function.
7973 *
7974 * \param - pHddCtx
7975 *
7976 * \return - None
7977 *
7978 * --------------------------------------------------------------------------*/
7979
7980static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
7981{
7982
7983 VOS_STATUS vos_status;
7984 /* Block any further calls */
7985 atomic_set(&pHddCtx->isRestartInProgress, 1);
7986 /* Cleanup */
7987 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
7988 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007989 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07007990 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
7991 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007992 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07007993
7994}
7995
7996/**---------------------------------------------------------------------------
7997 *
7998 * \brief wlan_hdd_framework_restart
7999 *
8000 * This function uses a cfg80211 API to start a framework initiated WLAN
8001 * driver module unload/load.
8002 *
8003 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8004 *
8005 *
8006 * \param - pHddCtx
8007 *
8008 * \return - VOS_STATUS_SUCCESS: Success
8009 * VOS_STATUS_E_EMPTY: Adapter is Empty
8010 * VOS_STATUS_E_NOMEM: No memory
8011
8012 * --------------------------------------------------------------------------*/
8013
8014static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8015{
8016 VOS_STATUS status = VOS_STATUS_SUCCESS;
8017 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008018 int len = (sizeof (struct ieee80211_mgmt));
8019 struct ieee80211_mgmt *mgmt = NULL;
8020
8021 /* Prepare the DEAUTH managment frame with reason code */
8022 mgmt = kzalloc(len, GFP_KERNEL);
8023 if(mgmt == NULL)
8024 {
8025 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8026 "%s: memory allocation failed (%d bytes)", __func__, len);
8027 return VOS_STATUS_E_NOMEM;
8028 }
8029 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008030
8031 /* Iterate over all adapters/devices */
8032 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8033 do
8034 {
8035 if( (status == VOS_STATUS_SUCCESS) &&
8036 pAdapterNode &&
8037 pAdapterNode->pAdapter)
8038 {
8039 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8040 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8041 pAdapterNode->pAdapter->dev->name,
8042 pAdapterNode->pAdapter->device_mode,
8043 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008044 /*
8045 * CFG80211 event to restart the driver
8046 *
8047 * 'cfg80211_send_unprot_deauth' sends a
8048 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8049 * of SME(Linux Kernel) state machine.
8050 *
8051 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8052 * the driver.
8053 *
8054 */
8055
8056 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008057 }
8058 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8059 pAdapterNode = pNext;
8060 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8061
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008062
8063 /* Free the allocated management frame */
8064 kfree(mgmt);
8065
Jeff Johnsone7245742012-09-05 17:12:55 -07008066 /* Retry until we unload or reach max count */
8067 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8068 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8069
8070 return status;
8071
8072}
8073/**---------------------------------------------------------------------------
8074 *
8075 * \brief wlan_hdd_restart_timer_cb
8076 *
8077 * Restart timer callback. An internal function.
8078 *
8079 * \param - User data:
8080 *
8081 * \return - None
8082 *
8083 * --------------------------------------------------------------------------*/
8084
8085void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8086{
8087 hdd_context_t *pHddCtx = usrDataForCallback;
8088 wlan_hdd_framework_restart(pHddCtx);
8089 return;
8090
8091}
8092
8093
8094/**---------------------------------------------------------------------------
8095 *
8096 * \brief wlan_hdd_restart_driver
8097 *
8098 * This function sends an event to supplicant to restart the WLAN driver.
8099 *
8100 * This function is called from vos_wlanRestart.
8101 *
8102 * \param - pHddCtx
8103 *
8104 * \return - VOS_STATUS_SUCCESS: Success
8105 * VOS_STATUS_E_EMPTY: Adapter is Empty
8106 * VOS_STATUS_E_ALREADY: Request already in progress
8107
8108 * --------------------------------------------------------------------------*/
8109VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8110{
8111 VOS_STATUS status = VOS_STATUS_SUCCESS;
8112
8113 /* A tight check to make sure reentrancy */
8114 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8115 {
8116 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8117 "%s: WLAN restart is already in progress", __func__);
8118
8119 return VOS_STATUS_E_ALREADY;
8120 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008121 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008122#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008123 wcnss_reset_intr();
8124#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008125
Jeff Johnsone7245742012-09-05 17:12:55 -07008126 return status;
8127}
8128
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008129/*
8130 * API to find if there is any STA or P2P-Client is connected
8131 */
8132VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8133{
8134 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8135}
Jeff Johnsone7245742012-09-05 17:12:55 -07008136
Jeff Johnson295189b2012-06-20 16:38:30 -07008137//Register the module init/exit functions
8138module_init(hdd_module_init);
8139module_exit(hdd_module_exit);
8140
8141MODULE_LICENSE("Dual BSD/GPL");
8142MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8143MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8144
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008145module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8146 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008147
Jeff Johnson76052702013-04-16 13:55:05 -07008148module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07008149 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);