blob: 307fae9063b9465d85b956d4f27132ea23947372 [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>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700112#include <linux/ctype.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#include <mach/subsystem_restart.h>
114#include <wlan_hdd_hostapd.h>
115#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700117#include "wlan_hdd_dev_pwr.h"
118#ifdef WLAN_BTAMP_FEATURE
119#include "bap_hdd_misc.h"
120#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700122#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800123#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530124#ifdef FEATURE_WLAN_TDLS
125#include "wlan_hdd_tdls.h"
126#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700127#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700128
129#ifdef MODULE
130#define WLAN_MODULE_NAME module_name(THIS_MODULE)
131#else
132#define WLAN_MODULE_NAME "wlan"
133#endif
134
135#ifdef TIMER_MANAGER
136#define TIMER_MANAGER_STR " +TIMER_MANAGER"
137#else
138#define TIMER_MANAGER_STR ""
139#endif
140
141#ifdef MEMORY_DEBUG
142#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
143#else
144#define MEMORY_DEBUG_STR ""
145#endif
146
147/* the Android framework expects this param even though we don't use it */
148#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700149static char fwpath_buffer[BUF_LEN];
150static struct kparam_string fwpath = {
151 .string = fwpath_buffer,
152 .maxlen = BUF_LEN,
153};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700155static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700156#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700157
Jeff Johnsone7245742012-09-05 17:12:55 -0700158/*
159 * The rate at which the driver sends RESTART event to supplicant
160 * once the function 'vos_wlanRestart()' is called
161 *
162 */
163#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
164#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700165
166/*
167 * Size of Driver command strings from upper layer
168 */
169#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
170#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
171
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700172/*
173 * Driver miracast parameters 0-Disabled
174 * 1-Source, 2-Sink
175 */
176#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
177#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
178
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800179#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700180static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700181#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700182/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700183static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700184
185//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700186static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
187static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
188static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
189void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800190void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700191
Jeff Johnson295189b2012-06-20 16:38:30 -0700192v_U16_t hdd_select_queue(struct net_device *dev,
193 struct sk_buff *skb);
194
195#ifdef WLAN_FEATURE_PACKET_FILTERING
196static void hdd_set_multicast_list(struct net_device *dev);
197#endif
198
199void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700200int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700201
202extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800203#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
204void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
205static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700206static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
207 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
208 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700209static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
210 tANI_U8 *pTargetApBssid,
211 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800212#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700213static int hdd_netdev_notifier_call(struct notifier_block * nb,
214 unsigned long state,
215 void *ndev)
216{
217 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700218 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700219 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700220#ifdef WLAN_BTAMP_FEATURE
221 VOS_STATUS status;
222 hdd_context_t *pHddCtx;
223#endif
224
225 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700226 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700227 (strncmp(dev->name, "p2p", 3)))
228 return NOTIFY_DONE;
229
230 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700231 return NOTIFY_DONE;
232
Jeff Johnson295189b2012-06-20 16:38:30 -0700233 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700234 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700235
Jeff Johnson27cee452013-03-27 11:10:24 -0700236 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700237 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800238 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700239 VOS_ASSERT(0);
240 return NOTIFY_DONE;
241 }
242
Jeff Johnson27cee452013-03-27 11:10:24 -0700243 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
244 if (NULL == pHddCtx)
245 {
246 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
247 VOS_ASSERT(0);
248 return NOTIFY_DONE;
249 }
250
251 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
252 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700253
254 switch (state) {
255 case NETDEV_REGISTER:
256 break;
257
258 case NETDEV_UNREGISTER:
259 break;
260
261 case NETDEV_UP:
262 break;
263
264 case NETDEV_DOWN:
265 break;
266
267 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700268 if(TRUE == pAdapter->isLinkUpSvcNeeded)
269 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 break;
271
272 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700273 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 {
275 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800276 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530277 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800279 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700280 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
281 if(!result)
282 {
283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800284 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700285 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700286 }
287 }
288 else
289 {
290 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700291 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700292 }
293#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700295 status = WLANBAP_StopAmp();
296 if(VOS_STATUS_SUCCESS != status )
297 {
298 pHddCtx->isAmpAllowed = VOS_TRUE;
299 hddLog(VOS_TRACE_LEVEL_FATAL,
300 "%s: Failed to stop AMP", __func__);
301 }
302 else
303 {
304 //a state m/c implementation in PAL is TBD to avoid this delay
305 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700306 if ( pHddCtx->isAmpAllowed )
307 {
308 WLANBAP_DeregisterFromHCI();
309 pHddCtx->isAmpAllowed = VOS_FALSE;
310 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700311 }
312#endif //WLAN_BTAMP_FEATURE
313 break;
314
315 default:
316 break;
317 }
318
319 return NOTIFY_DONE;
320}
321
322struct notifier_block hdd_netdev_notifier = {
323 .notifier_call = hdd_netdev_notifier_call,
324};
325
326/*---------------------------------------------------------------------------
327 * Function definitions
328 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700329void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
330void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700331//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700332static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700333#ifndef MODULE
334/* current con_mode - used only for statically linked driver
335 * con_mode is changed by userspace to indicate a mode change which will
336 * result in calling the module exit and init functions. The module
337 * exit function will clean up based on the value of con_mode prior to it
338 * being changed by userspace. So curr_con_mode records the current con_mode
339 * for exit when con_mode becomes the next mode for init
340 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700341static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700342#endif
343
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800344/**---------------------------------------------------------------------------
345
346 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
347
348 Called immediately after the cfg.ini is read in order to configure
349 the desired trace levels.
350
351 \param - moduleId - module whose trace level is being configured
352 \param - bitmask - bitmask of log levels to be enabled
353
354 \return - void
355
356 --------------------------------------------------------------------------*/
357static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
358{
359 wpt_tracelevel level;
360
361 /* if the bitmask is the default value, then a bitmask was not
362 specified in cfg.ini, so leave the logging level alone (it
363 will remain at the "compiled in" default value) */
364 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
365 {
366 return;
367 }
368
369 /* a mask was specified. start by disabling all logging */
370 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
371
372 /* now cycle through the bitmask until all "set" bits are serviced */
373 level = VOS_TRACE_LEVEL_FATAL;
374 while (0 != bitmask)
375 {
376 if (bitmask & 1)
377 {
378 vos_trace_setValue(moduleId, level, 1);
379 }
380 level++;
381 bitmask >>= 1;
382 }
383}
384
385
Jeff Johnson295189b2012-06-20 16:38:30 -0700386/**---------------------------------------------------------------------------
387
388 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
389
390 Called immediately after the cfg.ini is read in order to configure
391 the desired trace levels in the WDI.
392
393 \param - moduleId - module whose trace level is being configured
394 \param - bitmask - bitmask of log levels to be enabled
395
396 \return - void
397
398 --------------------------------------------------------------------------*/
399static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
400{
401 wpt_tracelevel level;
402
403 /* if the bitmask is the default value, then a bitmask was not
404 specified in cfg.ini, so leave the logging level alone (it
405 will remain at the "compiled in" default value) */
406 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
407 {
408 return;
409 }
410
411 /* a mask was specified. start by disabling all logging */
412 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
413
414 /* now cycle through the bitmask until all "set" bits are serviced */
415 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
416 while (0 != bitmask)
417 {
418 if (bitmask & 1)
419 {
420 wpalTraceSetLevel(moduleId, level, 1);
421 }
422 level++;
423 bitmask >>= 1;
424 }
425}
Jeff Johnson295189b2012-06-20 16:38:30 -0700426
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530427/*
428 * FUNCTION: wlan_hdd_validate_context
429 * This function is used to check the HDD context
430 */
431int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
432{
433 ENTER();
434
435 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
436 {
437 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
438 "%s: HDD context is Null", __func__);
439 return -ENODEV;
440 }
441
442 if (pHddCtx->isLogpInProgress)
443 {
444 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
445 "%s: LOGP in Progress. Ignore!!!", __func__);
446 return -EAGAIN;
447 }
448
449 if (pHddCtx->isLoadUnloadInProgress)
450 {
451 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
452 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
453 return -EAGAIN;
454 }
455 return 0;
456}
457
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530458void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
459{
460 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
461 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
462 hdd_config_t *cfg_param;
463 eCsrPhyMode phyMode;
464
465 if (NULL == pHddCtx)
466 {
467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
468 "HDD Context is null !!");
469 return ;
470 }
471
472 cfg_param = pHddCtx->cfg_ini;
473
474 if (NULL == cfg_param)
475 {
476 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
477 "cfg_params not available !!");
478 return ;
479 }
480
481 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
482
483 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
484 {
485 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
486 (eCSR_DOT11_MODE_11ac == phyMode) ||
487 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
488 {
489 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
490 "Setting phymode to 11n!!");
491 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
492 }
493 }
494 else
495 {
496 /*New country Supports 11ac as well resetting value back from .ini*/
497 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
498 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
499 return ;
500 }
501
502 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
503 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
504 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
505 {
506 VOS_STATUS vosStatus;
507
508 // need to issue a disconnect to CSR.
509 INIT_COMPLETION(pAdapter->disconnect_comp_var);
510 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
511 pAdapter->sessionId,
512 eCSR_DISCONNECT_REASON_UNSPECIFIED );
513
514 if (VOS_STATUS_SUCCESS == vosStatus)
515 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
516 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
517
518 }
519}
520
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700521void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
522{
523 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
524 hdd_config_t *cfg_param;
525
526 if (NULL == pHddCtx)
527 {
528 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
529 "HDD Context is null !!");
530 return ;
531 }
532
533 cfg_param = pHddCtx->cfg_ini;
534
535 if (NULL == cfg_param)
536 {
537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
538 "cfg_params not available !!");
539 return ;
540 }
541
542 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
543 {
544 /*New country doesn't support DFS */
545 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
546 }
547 else
548 {
549 /*New country Supports DFS as well resetting value back from .ini*/
550 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
551 }
552
553}
554
Rajeev79dbe4c2013-10-05 11:03:42 +0530555#ifdef FEATURE_WLAN_BATCH_SCAN
556
557/**---------------------------------------------------------------------------
558
559 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
560 input string
561
562 This function extracts assigned integer from string in below format:
563 "STRING=10" : extracts integer 10 from this string
564
565 \param - pInPtr Pointer to input string
566 \param - base Base for string to int conversion(10 for decimal 16 for hex)
567 \param - pOutPtr Pointer to variable in which extracted integer needs to be
568 assigned
569 \param - pLastArg to tell whether it is last arguement in input string or
570 not
571
572 \return - NULL for failure cases
573 pointer to next arguement in input string for success cases
574 --------------------------------------------------------------------------*/
575static tANI_U8 *
576hdd_extract_assigned_int_from_str
577(
578 tANI_U8 *pInPtr,
579 tANI_U8 base,
580 tANI_U32 *pOutPtr,
581 tANI_U8 *pLastArg
582)
583{
584 int tempInt;
585 int v = 0;
586 char buf[32];
587 int val = 0;
588 *pLastArg = FALSE;
589
590 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
591 if (NULL == pInPtr)
592 {
593 return NULL;
594 }
595
596 pInPtr++;
597
598 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
599
600 val = sscanf(pInPtr, "%32s ", buf);
601 if (val < 0 && val > strlen(pInPtr))
602 {
603 return NULL;
604 }
605 pInPtr += val;
606 v = kstrtos32(buf, base, &tempInt);
607 if (v < 0)
608 {
609 return NULL;
610 }
611 *pOutPtr = tempInt;
612
613 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
614 if (NULL == pInPtr)
615 {
616 *pLastArg = TRUE;
617 return NULL;
618 }
619 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
620
621 return pInPtr;
622}
623
624/**---------------------------------------------------------------------------
625
626 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
627 input string
628
629 This function extracts assigned character from string in below format:
630 "STRING=A" : extracts char 'A' from this string
631
632 \param - pInPtr Pointer to input string
633 \param - pOutPtr Pointer to variable in which extracted char needs to be
634 assigned
635 \param - pLastArg to tell whether it is last arguement in input string or
636 not
637
638 \return - NULL for failure cases
639 pointer to next arguement in input string for success cases
640 --------------------------------------------------------------------------*/
641static tANI_U8 *
642hdd_extract_assigned_char_from_str
643(
644 tANI_U8 *pInPtr,
645 tANI_U8 *pOutPtr,
646 tANI_U8 *pLastArg
647)
648{
649 *pLastArg = FALSE;
650
651 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
652 if (NULL == pInPtr)
653 {
654 return NULL;
655 }
656
657 pInPtr++;
658
659 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
660
661 *pOutPtr = *pInPtr;
662
663 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
664 if (NULL == pInPtr)
665 {
666 *pLastArg = TRUE;
667 return NULL;
668 }
669 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
670
671 return pInPtr;
672}
673
674
675/**---------------------------------------------------------------------------
676
677 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
678
679 This function parses set batch scan command in below format:
680 WLS_BATCHING_SET <space> followed by below arguements
681 "SCANFREQ=XX" : Optional defaults to 30 sec
682 "MSCAN=XX" : Required number of scans to attempt to batch
683 "BESTN=XX" : Best Network (RSSI) defaults to 16
684 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
685 A. implies only 5 GHz , B. implies only 2.4GHz
686 "RTT=X" : optional defaults to 0
687 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
688 error
689
690 For example input commands:
691 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
692 translated into set batch scan with following parameters:
693 a) Frequence 60 seconds
694 b) Batch 10 scans together
695 c) Best RSSI to be 20
696 d) 5GHz band only
697 e) RTT is equal to 0
698
699 \param - pValue Pointer to input channel list
700 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
701
702 \return - 0 for success non-zero for failure
703
704 --------------------------------------------------------------------------*/
705static int
706hdd_parse_set_batchscan_command
707(
708 tANI_U8 *pValue,
709 tSirSetBatchScanReq *pHddSetBatchScanReq
710)
711{
712 tANI_U8 *inPtr = pValue;
713 tANI_U8 val = 0;
714 tANI_U8 lastArg = 0;
715
716 /*initialize default values*/
717 pHddSetBatchScanReq->scanFrequency = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
718 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
719 pHddSetBatchScanReq->rtt = 0;
720 pHddSetBatchScanReq->bestNetwork = HDD_SET_BATCH_SCAN_BEST_NETWORK;
721
722 /*go to space after WLS_BATCHING_SET command*/
723 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
724 /*no argument after the command*/
725 if (NULL == inPtr)
726 {
727 return -EINVAL;
728 }
729
730 /*no space after the command*/
731 else if (SPACE_ASCII_VALUE != *inPtr)
732 {
733 return -EINVAL;
734 }
735
736 /*removing empty spaces*/
737 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
738
739 /*no argument followed by spaces*/
740 if ('\0' == *inPtr)
741 {
742 return -EINVAL;
743 }
744
745 /*check and parse SCANFREQ*/
746 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
747 {
748 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
749 &pHddSetBatchScanReq->scanFrequency, &lastArg);
750 if ( (NULL == inPtr) || (TRUE == lastArg))
751 {
752 return -EINVAL;
753 }
754 }
755
756 /*check and parse MSCAN*/
757 if ((strncmp(inPtr, "MSCAN", 5) == 0))
758 {
759 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
760 &pHddSetBatchScanReq->numberOfScansToBatch, &lastArg);
761 if (TRUE == lastArg)
762 {
763 goto done;
764 }
765 else if (NULL == inPtr)
766 {
767 return -EINVAL;
768 }
769 }
770 else
771 {
772 return -EINVAL;
773 }
774
775 /*check and parse BESTN*/
776 if ((strncmp(inPtr, "BESTN", 5) == 0))
777 {
778 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
779 &pHddSetBatchScanReq->bestNetwork, &lastArg);
780 if (TRUE == lastArg)
781 {
782 goto done;
783 }
784 else if (NULL == inPtr)
785 {
786 return -EINVAL;
787 }
788 }
789
790 /*check and parse CHANNEL*/
791 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
792 {
793 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
794 if (TRUE == lastArg)
795 {
796 goto done;
797 }
798 else if (NULL == inPtr)
799 {
800 return -EINVAL;
801 }
802 if (('A' == val) || ('a' == val))
803 {
804 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
805 }
806 else if (('B' == val) || ('b' == val))
807 {
808 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
809 }
810 else
811 {
812 return -EINVAL;
813 }
814 }
815
816 /*check and parse RTT*/
817 if ((strncmp(inPtr, "RTT", 3) == 0))
818 {
819 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
820 &pHddSetBatchScanReq->rtt, &lastArg);
821 if (TRUE == lastArg)
822 {
823 goto done;
824 }
825 if (NULL == inPtr)
826 {
827 return -EINVAL;
828 }
829 }
830
831
832done:
833
834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
835 "Received WLS_BATCHING_SET with SCANFREQ=%d "
836 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
837 pHddSetBatchScanReq->scanFrequency,
838 pHddSetBatchScanReq->numberOfScansToBatch,
839 pHddSetBatchScanReq->bestNetwork,
840 pHddSetBatchScanReq->rfBand,
841 pHddSetBatchScanReq->rtt);
842
843 return 0;
844}/*End of hdd_parse_set_batchscan_command*/
845
846/**---------------------------------------------------------------------------
847
848 \brief hdd_set_batch_scan_req_callback () - This function is called after
849 receiving set batch scan response from FW and it saves set batch scan
850 response data FW to HDD context and sets the completion event on
851 which hdd_ioctl is waiting
852
853 \param - callbackContext Pointer to HDD adapter
854 \param - pRsp Pointer to set batch scan response data received from FW
855
856 \return - nothing
857
858 --------------------------------------------------------------------------*/
859static void hdd_set_batch_scan_req_callback
860(
861 void *callbackContext,
862 tSirSetBatchScanRsp *pRsp
863)
864{
865 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
866 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
867
868 /*sanity check*/
869 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
870 {
871 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
872 "%s: Invalid pAdapter magic", __func__);
873 VOS_ASSERT(0);
874 return;
875 }
876 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
877
878 /*save set batch scan response*/
879 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
880
881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
882 "Received set batch scan rsp from FW with nScansToBatch=%d",
883 pHddSetBatchScanRsp->nScansToBatch);
884
885 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
886 complete(&pAdapter->hdd_set_batch_scan_req_var);
887
888 return;
889}/*End of hdd_set_batch_scan_req_callback*/
890
891
892/**---------------------------------------------------------------------------
893
894 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
895 info in hdd batch scan response queue
896
897 \param - pAdapter Pointer to hdd adapter
898 \param - pAPMetaInfo Pointer to access point meta info
899 \param - scanId scan ID of batch scan response
900 \param - isLastAp tells whether AP is last AP in batch scan response or not
901
902 \return - nothing
903
904 --------------------------------------------------------------------------*/
905static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
906 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
907{
908 tHddBatchScanRsp *pHead;
909 tHddBatchScanRsp *pNode;
910 tHddBatchScanRsp *pPrev;
911 tHddBatchScanRsp *pTemp;
912 tANI_U8 ssidLen;
913
914 /*head of hdd batch scan response queue*/
915 pHead = pAdapter->pBatchScanRsp;
916
917 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
918 if (NULL == pNode)
919 {
920 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
921 "%s: Could not allocate memory", __func__);
922 VOS_ASSERT(0);
923 return;
924 }
925
926 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
927 sizeof(pNode->ApInfo.bssid));
928 ssidLen = strlen(pApMetaInfo->ssid);
929 if (SIR_MAX_SSID_SIZE < ssidLen)
930 {
931 /*invalid scan result*/
932 vos_mem_free(pNode);
933 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
934 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
935 return;
936 }
937 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
938 /*null terminate ssid*/
939 pNode->ApInfo.ssid[ssidLen] = '\0';
940 pNode->ApInfo.ch = pApMetaInfo->ch;
941 pNode->ApInfo.rssi = pApMetaInfo->rssi;
942 pNode->ApInfo.age = pApMetaInfo->timestamp;
943 pNode->ApInfo.batchId = scanId;
944 pNode->ApInfo.isLastAp = isLastAp;
945
946 pNode->pNext = NULL;
947 if (NULL == pHead)
948 {
949 pAdapter->pBatchScanRsp = pNode;
950 }
951 else
952 {
953 pTemp = pHead;
954 while (NULL != pTemp)
955 {
956 pPrev = pTemp;
957 pTemp = pTemp->pNext;
958 }
959 pPrev->pNext = pNode;
960 }
961
962 return;
963}/*End of hdd_populate_batch_scan_rsp_queue*/
964
965/**---------------------------------------------------------------------------
966
967 \brief hdd_batch_scan_result_ind_callback () - This function is called after
968 receiving batch scan response indication from FW. It saves get batch scan
969 response data in HDD batch scan response queue. This callback sets the
970 completion event on which hdd_ioctl is waiting only after getting complete
971 batch scan response data from FW
972
973 \param - callbackContext Pointer to HDD adapter
974 \param - pRsp Pointer to get batch scan response data received from FW
975
976 \return - nothing
977
978 --------------------------------------------------------------------------*/
979static void hdd_batch_scan_result_ind_callback
980(
981 void *callbackContext,
982 void *pRsp
983)
984{
985 v_BOOL_t isLastAp;
986 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -0700987 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +0530988 tANI_U32 numberScanList;
989 tANI_U32 nextScanListOffset;
990 tANI_U32 nextApMetaInfoOffset;
991 hdd_adapter_t* pAdapter;
992 tpSirBatchScanList pScanList;
993 tpSirBatchScanNetworkInfo pApMetaInfo;
994 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
995 tSirSetBatchScanReq *pReq;
996
997 pAdapter = (hdd_adapter_t *)callbackContext;
998 /*sanity check*/
999 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1000 {
1001 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1002 "%s: Invalid pAdapter magic", __func__);
1003 VOS_ASSERT(0);
1004 return;
1005 }
1006
1007 /*initialize locals*/
1008 pReq = &pAdapter->hddSetBatchScanReq;
1009 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1010 isLastAp = FALSE;
1011 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001012 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301013 numberScanList = 0;
1014 nextScanListOffset = 0;
1015 nextApMetaInfoOffset = 0;
1016 pScanList = NULL;
1017 pApMetaInfo = NULL;
1018
1019 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1020 {
1021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1022 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1023 isLastAp = TRUE;
1024 goto done;
1025 }
1026
1027 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1028 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1029 "Batch scan rsp: numberScalList %d", numberScanList);
1030
1031 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1032 {
1033 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1034 "%s: numberScanList %d", __func__, numberScanList);
1035 isLastAp = TRUE;
1036 goto done;
1037 }
1038
1039 while (numberScanList)
1040 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001041 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301042 nextScanListOffset);
1043 if (NULL == pScanList)
1044 {
1045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1046 "%s: pScanList is %p", __func__, pScanList);
1047 isLastAp = TRUE;
1048 goto done;
1049 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001050 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301051 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001052 "Batch scan rsp: numApMetaInfo %d scanId %d",
1053 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301054
1055 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1056 {
1057 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1058 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1059 isLastAp = TRUE;
1060 goto done;
1061 }
1062
Rajeev Kumarce651e42013-10-21 18:57:15 -07001063 /*Initialize next AP meta info offset for next scan list*/
1064 nextApMetaInfoOffset = 0;
1065
Rajeev79dbe4c2013-10-05 11:03:42 +05301066 while (numApMetaInfo)
1067 {
1068 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1069 nextApMetaInfoOffset);
1070 if (NULL == pApMetaInfo)
1071 {
1072 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1073 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1074 isLastAp = TRUE;
1075 goto done;
1076 }
1077 /*calculate AP age*/
1078 pApMetaInfo->timestamp =
1079 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1080
1081 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1082 "%s: bssId 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x "
1083 "ch %d rssi %d timestamp %d", __func__,
1084 pApMetaInfo->bssid[0],pApMetaInfo->bssid[1],
1085 pApMetaInfo->bssid[2],pApMetaInfo->bssid[3],
1086 pApMetaInfo->bssid[4],pApMetaInfo->bssid[5],
1087 pApMetaInfo->ch, pApMetaInfo->rssi,
1088 pApMetaInfo->timestamp);
1089
1090 /*mark last AP in batch scan response*/
1091 if ((TRUE == pBatchScanRsp->isLastResult) &&
1092 (1 == numberScanList) && (1 == numApMetaInfo))
1093 {
1094 isLastAp = TRUE;
1095 }
1096
1097 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1098 /*store batch scan repsonse in hdd queue*/
1099 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1100 pScanList->scanId, isLastAp);
1101 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1102
1103 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1104 numApMetaInfo--;
1105 }
1106
Rajeev Kumarce651e42013-10-21 18:57:15 -07001107 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1108 + (sizeof(tSirBatchScanNetworkInfo)
1109 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301110 numberScanList--;
1111 }
1112
1113done:
1114
1115 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1116 requested from hdd_ioctl*/
1117 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1118 (TRUE == isLastAp))
1119 {
1120 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1121 complete(&pAdapter->hdd_get_batch_scan_req_var);
1122 }
1123
1124 return;
1125}/*End of hdd_batch_scan_result_ind_callback*/
1126
1127/**---------------------------------------------------------------------------
1128
1129 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1130 response as per batch scan FR request format by putting proper markers
1131
1132 \param - pDest pointer to destination buffer
1133 \param - cur_len current length
1134 \param - tot_len total remaining size which can be written to user space
1135 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1136 \param - pAdapter Pointer to HDD adapter
1137
1138 \return - ret no of characters written
1139
1140 --------------------------------------------------------------------------*/
1141static tANI_U32
1142hdd_format_batch_scan_rsp
1143(
1144 tANI_U8 *pDest,
1145 tANI_U32 cur_len,
1146 tANI_U32 tot_len,
1147 tHddBatchScanRsp *pApMetaInfo,
1148 hdd_adapter_t* pAdapter
1149)
1150{
1151 tANI_U32 ret = 0;
1152 tANI_U32 rem_len = 0;
1153 tANI_U8 temp_len = 0;
1154 tANI_U8 temp_total_len = 0;
1155 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1156 tANI_U8 *pTemp = temp;
1157
1158 /*Batch scan reponse needs to be returned to user space in
1159 following format:
1160 "scancount=X\n" where X is the number of scans in current batch
1161 batch
1162 "trunc\n" optional present if current scan truncated
1163 "bssid=XX:XX:XX:XX:XX:XX\n"
1164 "ssid=XXXX\n"
1165 "freq=X\n" frequency in Mhz
1166 "level=XX\n"
1167 "age=X\n" ms
1168 "dist=X\n" cm (-1 if not available)
1169 "errror=X\n" (-1if not available)
1170 "====\n" (end of ap marker)
1171 "####\n" (end of scan marker)
1172 "----\n" (end of results)*/
1173 /*send scan result in above format to user space based on
1174 available length*/
1175 /*The GET response may have more data than the driver can return in its
1176 buffer. In that case the buffer should be filled to the nearest complete
1177 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1178 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1179 The final buffer should end with "----\n"*/
1180
1181 /*sanity*/
1182 if (cur_len > tot_len)
1183 {
1184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1185 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1186 return 0;
1187 }
1188 else
1189 {
1190 rem_len = (tot_len - cur_len);
1191 }
1192
1193 /*end scan marker*/
1194 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1195 {
1196 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1197 pTemp += temp_len;
1198 temp_total_len += temp_len;
1199 }
1200
1201 /*bssid*/
1202 temp_len = snprintf(pTemp, sizeof(temp),
1203 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1204 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1205 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1206 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1207 pTemp += temp_len;
1208 temp_total_len += temp_len;
1209
1210 /*ssid*/
1211 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1212 pApMetaInfo->ApInfo.ssid);
1213 pTemp += temp_len;
1214 temp_total_len += temp_len;
1215
1216 /*freq*/
1217 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
1218 pApMetaInfo->ApInfo.ch);
1219 pTemp += temp_len;
1220 temp_total_len += temp_len;
1221
1222 /*level*/
1223 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1224 pApMetaInfo->ApInfo.rssi);
1225 pTemp += temp_len;
1226 temp_total_len += temp_len;
1227
1228 /*age*/
1229 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%ld\n",
1230 pApMetaInfo->ApInfo.age);
1231 pTemp += temp_len;
1232 temp_total_len += temp_len;
1233
1234 /*dist*/
1235 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1236 pTemp += temp_len;
1237 temp_total_len += temp_len;
1238
1239 /*error*/
1240 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1241 pTemp += temp_len;
1242 temp_total_len += temp_len;
1243
1244 /*end AP marker*/
1245 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1246 pTemp += temp_len;
1247 temp_total_len += temp_len;
1248
1249 /*last AP in batch scan response*/
1250 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1251 {
1252 /*end scan marker*/
1253 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1254 pTemp += temp_len;
1255 temp_total_len += temp_len;
1256
1257 /*end batch scan result marker*/
1258 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1259 pTemp += temp_len;
1260 temp_total_len += temp_len;
1261 }
1262
1263 if (temp_total_len < rem_len)
1264 {
1265 ret = temp_total_len + 1;
1266 strlcpy(pDest, temp, ret);
1267 pAdapter->isTruncated = FALSE;
1268 }
1269 else
1270 {
1271 pAdapter->isTruncated = TRUE;
1272 if (rem_len >= strlen("%%%%"))
1273 {
1274 ret = snprintf(pDest, strlen("%%%%"), "%%%%");
1275 }
1276 {
1277 ret = 0;
1278 }
1279 }
1280
1281 return ret;
1282
1283}/*End of hdd_format_batch_scan_rsp*/
1284
1285/**---------------------------------------------------------------------------
1286
1287 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1288 buffer starting with head of hdd batch scan response queue
1289
1290 \param - pAdapter Pointer to HDD adapter
1291 \param - pDest Pointer to user data buffer
1292 \param - cur_len current offset in user buffer
1293 \param - rem_len remaining no of bytes in user buffer
1294
1295 \return - number of bytes written in user buffer
1296
1297 --------------------------------------------------------------------------*/
1298
1299tANI_U32 hdd_populate_user_batch_scan_rsp
1300(
1301 hdd_adapter_t* pAdapter,
1302 tANI_U8 *pDest,
1303 tANI_U32 cur_len,
1304 tANI_U32 rem_len
1305)
1306{
1307 tHddBatchScanRsp *pHead;
1308 tHddBatchScanRsp *pPrev;
1309 tANI_U32 len;
1310
1311 pAdapter->prev_batch_id = 0;
1312 pAdapter->isTruncated = FALSE;
1313
1314 /*head of hdd batch scan response queue*/
1315 pHead = pAdapter->pBatchScanRsp;
1316 while (pHead)
1317 {
1318 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1319 pAdapter);
1320 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001321 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301322 cur_len += len;
1323 if(TRUE == pAdapter->isTruncated)
1324 {
1325 /*result is truncated return rest of scan rsp in next req*/
1326 cur_len = rem_len;
1327 break;
1328 }
1329 pPrev = pHead;
1330 pHead = pHead->pNext;
1331 pAdapter->pBatchScanRsp = pHead;
1332 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1333 vos_mem_free(pPrev);
1334 }
1335
1336 return cur_len;
1337}/*End of hdd_populate_user_batch_scan_rsp*/
1338
1339/**---------------------------------------------------------------------------
1340
1341 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1342 scan response data from HDD queue to user space
1343 It does following in detail:
1344 a) if HDD has enough data in its queue then it 1st copies data to user
1345 space and then send get batch scan indication message to FW. In this
1346 case it does not wait on any event and batch scan response data will
1347 be populated in HDD response queue in MC thread context after receiving
1348 indication from FW
1349 b) else send get batch scan indication message to FW and wait on an event
1350 which will be set once HDD receives complete batch scan response from
1351 FW and then this function returns batch scan response to user space
1352
1353 \param - pAdapter Pointer to HDD adapter
1354 \param - pPrivData Pointer to priv_data
1355
1356 \return - 0 for success -EFAULT for failure
1357
1358 --------------------------------------------------------------------------*/
1359
1360int hdd_return_batch_scan_rsp_to_user
1361(
1362 hdd_adapter_t* pAdapter,
1363 hdd_priv_data_t *pPrivData,
1364 tANI_U8 *command
1365)
1366{
1367 tANI_U8 *pDest;
1368 tANI_U32 count = 0;
1369 tANI_U32 len = 0;
1370 tANI_U32 cur_len = 0;
1371 tANI_U32 rem_len = 0;
1372 eHalStatus halStatus;
1373 unsigned long rc;
1374 tSirTriggerBatchScanResultInd *pReq;
1375
1376 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1377 pReq->param = 0;/*batch scan client*/
1378 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1379 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1380
1381 cur_len = pPrivData->used_len;
1382 if (pPrivData->total_len > pPrivData->used_len)
1383 {
1384 rem_len = pPrivData->total_len - pPrivData->used_len;
1385 }
1386 else
1387 {
1388 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1389 "%s: Invalid user data buffer total_len %d used_len %d",
1390 __func__, pPrivData->total_len, pPrivData->used_len);
1391 return -EFAULT;
1392 }
1393
1394 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1395 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1396 cur_len, rem_len);
1397 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1398
1399 /*enough scan result available in cache to return to user space or
1400 scan result needs to be fetched 1st from fw and then return*/
1401 if (len < rem_len)
1402 {
1403 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1404 halStatus = sme_TriggerBatchScanResultInd(
1405 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1406 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1407 pAdapter);
1408 if ( eHAL_STATUS_SUCCESS == halStatus )
1409 {
1410 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1411 {
1412 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1413 rc = wait_for_completion_timeout(
1414 &pAdapter->hdd_get_batch_scan_req_var,
1415 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1416 if (0 == rc)
1417 {
1418 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1419 "%s: Timeout waiting to fetch batch scan rsp from fw",
1420 __func__);
1421 return -EFAULT;
1422 }
1423 }
1424
1425 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
1426 "scancount=%ld\n", pAdapter->numScanList);
1427 pDest += len;
1428 cur_len += len;
1429
1430 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1431 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1432 cur_len, rem_len);
1433 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1434
1435 count = 0;
1436 len = (len - pPrivData->used_len);
1437 pDest = (command + pPrivData->used_len);
1438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1439 "BATCH SCAN RESULT:");
1440 while(count < len)
1441 {
1442 printk("%c", *(pDest + count));
1443 count++;
1444 }
1445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1446 "%s: copy %d data to user buffer", __func__, len);
1447 if (copy_to_user(pPrivData->buf, pDest, len))
1448 {
1449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1450 "%s: failed to copy data to user buffer", __func__);
1451 return -EFAULT;
1452 }
1453 }
1454 else
1455 {
1456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1457 "sme_GetBatchScanScan returned failure halStatus %d",
1458 halStatus);
1459 return -EINVAL;
1460 }
1461 }
1462 else
1463 {
1464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1465 "%s: copy %d data to user buffer", __func__, len);
1466 count = 0;
1467 len = (len - pPrivData->used_len);
1468 pDest = (command + pPrivData->used_len);
1469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1470 "BATCH SCAN RESULT:");
1471 while(count < len)
1472 {
1473 printk("%c", *(pDest + count));
1474 count++;
1475 }
1476 if (copy_to_user(pPrivData->buf, pDest, len))
1477 {
1478 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1479 "%s: failed to copy data to user buffer", __func__);
1480 return -EFAULT;
1481 }
1482 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1483 halStatus = sme_TriggerBatchScanResultInd(
1484 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1485 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1486 pAdapter);
1487 if ( eHAL_STATUS_SUCCESS != halStatus )
1488 {
1489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1490 "sme_GetBatchScanScan returned failure halStatus %d",
1491 halStatus);
1492 }
1493 }
1494
1495 return 0;
1496} /*End of hdd_return_batch_scan_rsp_to_user*/
1497
1498#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1499
Jeff Johnson295189b2012-06-20 16:38:30 -07001500int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1501{
1502 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1503 hdd_priv_data_t priv_data;
1504 tANI_U8 *command = NULL;
1505 int ret = 0;
1506
1507 if (NULL == pAdapter)
1508 {
1509 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001510 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001511 ret = -ENODEV;
1512 goto exit;
1513 }
1514
Jeff Johnsone7245742012-09-05 17:12:55 -07001515 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001516 {
1517 ret = -EINVAL;
1518 goto exit;
1519 }
1520
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001521 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1522 {
1523 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1524 "%s:LOGP in Progress. Ignore!!!", __func__);
1525 ret = -EBUSY;
1526 goto exit;
1527 }
1528
Jeff Johnson295189b2012-06-20 16:38:30 -07001529 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1530 {
1531 ret = -EFAULT;
1532 goto exit;
1533 }
1534
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001535 if (priv_data.total_len <= 0)
1536 {
1537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1538 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1539 priv_data.total_len);
1540 ret = -EINVAL;
1541 goto exit;
1542 }
1543
1544 /* Allocate +1 for '\0' */
1545 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001546 if (!command)
1547 {
1548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001549 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001550 ret = -ENOMEM;
1551 goto exit;
1552 }
1553
1554 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1555 {
1556 ret = -EFAULT;
1557 goto exit;
1558 }
1559
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001560 /* Making sure the command is NUL-terminated */
1561 command[priv_data.total_len] = '\0';
1562
Jeff Johnson295189b2012-06-20 16:38:30 -07001563 if ((SIOCDEVPRIVATE + 1) == cmd)
1564 {
1565 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1566
1567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001568 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001569
1570 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1571 {
1572 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1573 sizeof(tSirMacAddr)))
1574 {
1575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001576 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001577 ret = -EFAULT;
1578 }
1579 }
Amar Singhal0974e402013-02-12 14:27:46 -08001580 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001581 {
Amar Singhal0974e402013-02-12 14:27:46 -08001582 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001583 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001584
Jeff Johnson295189b2012-06-20 16:38:30 -07001585 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001586
1587 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001588 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001589 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001590 "%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 -07001591 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001592 ret = hdd_setBand_helper(dev, ptr);
1593 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001594 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1595 {
1596 char *country_code;
1597
1598 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001599
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001600 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001601 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301602 hdd_checkandupdate_phymode(pAdapter, country_code);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001603 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1604 (void *)(tSmeChangeCountryCallback)
1605 wlan_hdd_change_country_code_callback,
1606 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1607 if (eHAL_STATUS_SUCCESS == ret)
1608 {
1609 ret = wait_for_completion_interruptible_timeout(
1610 &pAdapter->change_country_code,
1611 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1612 if (0 >= ret)
1613 {
1614 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1615 __func__);
1616 }
1617 }
1618 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001619 {
1620 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001621 "%s: SME Change Country code fail ret=%d", __func__, ret);
1622 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001623 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001624
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001625 }
1626 /*
1627 command should be a string having format
1628 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1629 */
Amar Singhal0974e402013-02-12 14:27:46 -08001630 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001631 {
Amar Singhal0974e402013-02-12 14:27:46 -08001632 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001633
1634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001635 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001636
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001637 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001638 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001639 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1640 {
1641 int suspend = 0;
1642 tANI_U8 *ptr = (tANI_U8*)command + 15;
1643
1644 suspend = *ptr - '0';
1645 hdd_set_wlan_suspend_mode(suspend);
1646 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001647#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1648 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1649 {
1650 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001651 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001652 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1653 eHalStatus status = eHAL_STATUS_SUCCESS;
1654
1655 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1656 value = value + 15;
1657
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001658 /* Convert the value from ascii to integer */
1659 ret = kstrtos8(value, 10, &rssi);
1660 if (ret < 0)
1661 {
1662 /* If the input value is greater than max value of datatype, then also
1663 kstrtou8 fails */
1664 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1665 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
1666 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1667 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1668 ret = -EINVAL;
1669 goto exit;
1670 }
1671
Srinivas Girigowdade697412013-02-14 16:31:48 -08001672 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001673
Srinivas Girigowdade697412013-02-14 16:31:48 -08001674 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1675 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1676 {
1677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1678 "Neighbor lookup threshold value %d is out of range"
1679 " (Min: %d Max: %d)", lookUpThreshold,
1680 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1681 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1682 ret = -EINVAL;
1683 goto exit;
1684 }
1685
1686 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1687 "%s: Received Command to Set Roam trigger"
1688 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1689
1690 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1691 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1692 if (eHAL_STATUS_SUCCESS != status)
1693 {
1694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1695 "%s: Failed to set roam trigger, try again", __func__);
1696 ret = -EPERM;
1697 goto exit;
1698 }
1699
1700 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1701 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1702 }
1703 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1704 {
1705 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1706 int rssi = (-1) * lookUpThreshold;
1707 char extra[32];
1708 tANI_U8 len = 0;
1709
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001710 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001711 if (copy_to_user(priv_data.buf, &extra, len + 1))
1712 {
1713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1714 "%s: failed to copy data to user buffer", __func__);
1715 ret = -EFAULT;
1716 goto exit;
1717 }
1718 }
1719 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1720 {
1721 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001722 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001723 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001724
Srinivas Girigowdade697412013-02-14 16:31:48 -08001725 /* input refresh period is in terms of seconds */
1726 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1727 value = value + 18;
1728 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001729 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001730 if (ret < 0)
1731 {
1732 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001733 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001735 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001736 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001737 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1738 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001739 ret = -EINVAL;
1740 goto exit;
1741 }
1742
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001743 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1744 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001745 {
1746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001747 "Roam scan period value %d is out of range"
1748 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001749 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1750 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001751 ret = -EINVAL;
1752 goto exit;
1753 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001754 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001755
1756 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1757 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001758 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001759
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001760 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1761 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001762 }
1763 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1764 {
1765 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1766 char extra[32];
1767 tANI_U8 len = 0;
1768
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001769 len = scnprintf(extra, sizeof(extra), "%s %d",
1770 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001771 /* Returned value is in units of seconds */
1772 if (copy_to_user(priv_data.buf, &extra, len + 1))
1773 {
1774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1775 "%s: failed to copy data to user buffer", __func__);
1776 ret = -EFAULT;
1777 goto exit;
1778 }
1779 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001780 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1781 {
1782 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001783 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001784 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001785
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001786 /* input refresh period is in terms of seconds */
1787 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1788 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001789
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001790 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001791 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001792 if (ret < 0)
1793 {
1794 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001795 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001797 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001798 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001799 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1800 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1801 ret = -EINVAL;
1802 goto exit;
1803 }
1804
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001805 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1806 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1807 {
1808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1809 "Neighbor scan results refresh period value %d is out of range"
1810 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1811 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1812 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1813 ret = -EINVAL;
1814 goto exit;
1815 }
1816 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1817
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1819 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001820 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001821
1822 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1823 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1824 }
1825 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1826 {
1827 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1828 char extra[32];
1829 tANI_U8 len = 0;
1830
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001831 len = scnprintf(extra, sizeof(extra), "%s %d",
1832 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001833 /* Returned value is in units of seconds */
1834 if (copy_to_user(priv_data.buf, &extra, len + 1))
1835 {
1836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1837 "%s: failed to copy data to user buffer", __func__);
1838 ret = -EFAULT;
1839 goto exit;
1840 }
1841 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001842#ifdef FEATURE_WLAN_LFR
1843 /* SETROAMMODE */
1844 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1845 {
1846 tANI_U8 *value = command;
1847 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1848
1849 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1850 value = value + SIZE_OF_SETROAMMODE + 1;
1851
1852 /* Convert the value from ascii to integer */
1853 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1854 if (ret < 0)
1855 {
1856 /* If the input value is greater than max value of datatype, then also
1857 kstrtou8 fails */
1858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1859 "%s: kstrtou8 failed range [%d - %d]", __func__,
1860 CFG_LFR_FEATURE_ENABLED_MIN,
1861 CFG_LFR_FEATURE_ENABLED_MAX);
1862 ret = -EINVAL;
1863 goto exit;
1864 }
1865 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1866 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1867 {
1868 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1869 "Roam Mode value %d is out of range"
1870 " (Min: %d Max: %d)", roamMode,
1871 CFG_LFR_FEATURE_ENABLED_MIN,
1872 CFG_LFR_FEATURE_ENABLED_MAX);
1873 ret = -EINVAL;
1874 goto exit;
1875 }
1876
1877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1878 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
1879 /*
1880 * Note that
1881 * SETROAMMODE 0 is to enable LFR while
1882 * SETROAMMODE 1 is to disable LFR, but
1883 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
1884 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
1885 */
1886 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1887 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
1888 else
1889 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
1890
1891 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
1892 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
1893 }
1894 /* GETROAMMODE */
1895 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
1896 {
1897 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1898 char extra[32];
1899 tANI_U8 len = 0;
1900
1901 /*
1902 * roamMode value shall be inverted because the sementics is different.
1903 */
1904 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1905 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
1906 else
1907 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
1908
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001909 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001910 if (copy_to_user(priv_data.buf, &extra, len + 1))
1911 {
1912 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1913 "%s: failed to copy data to user buffer", __func__);
1914 ret = -EFAULT;
1915 goto exit;
1916 }
1917 }
1918#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08001919#endif
1920#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1921 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1922 {
1923 tANI_U8 *value = command;
1924 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1925
1926 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1927 value = value + 13;
1928 /* Convert the value from ascii to integer */
1929 ret = kstrtou8(value, 10, &roamRssiDiff);
1930 if (ret < 0)
1931 {
1932 /* If the input value is greater than max value of datatype, then also
1933 kstrtou8 fails */
1934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1935 "%s: kstrtou8 failed range [%d - %d]", __func__,
1936 CFG_ROAM_RSSI_DIFF_MIN,
1937 CFG_ROAM_RSSI_DIFF_MAX);
1938 ret = -EINVAL;
1939 goto exit;
1940 }
1941
1942 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1943 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1944 {
1945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1946 "Roam rssi diff value %d is out of range"
1947 " (Min: %d Max: %d)", roamRssiDiff,
1948 CFG_ROAM_RSSI_DIFF_MIN,
1949 CFG_ROAM_RSSI_DIFF_MAX);
1950 ret = -EINVAL;
1951 goto exit;
1952 }
1953
1954 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1955 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1956
1957 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1958 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1959 }
1960 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1961 {
1962 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1963 char extra[32];
1964 tANI_U8 len = 0;
1965
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001966 len = scnprintf(extra, sizeof(extra), "%s %d",
1967 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001968 if (copy_to_user(priv_data.buf, &extra, len + 1))
1969 {
1970 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1971 "%s: failed to copy data to user buffer", __func__);
1972 ret = -EFAULT;
1973 goto exit;
1974 }
1975 }
1976#endif
1977#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1978 else if (strncmp(command, "GETBAND", 7) == 0)
1979 {
1980 int band = -1;
1981 char extra[32];
1982 tANI_U8 len = 0;
1983 hdd_getBand_helper(pHddCtx, &band);
1984
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001985 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001986 if (copy_to_user(priv_data.buf, &extra, len + 1))
1987 {
1988 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1989 "%s: failed to copy data to user buffer", __func__);
1990 ret = -EFAULT;
1991 goto exit;
1992 }
1993 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001994 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1995 {
1996 tANI_U8 *value = command;
1997 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1998 tANI_U8 numChannels = 0;
1999 eHalStatus status = eHAL_STATUS_SUCCESS;
2000
2001 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2002 if (eHAL_STATUS_SUCCESS != status)
2003 {
2004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2005 "%s: Failed to parse channel list information", __func__);
2006 ret = -EINVAL;
2007 goto exit;
2008 }
2009
2010 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2011 {
2012 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2013 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2014 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2015 ret = -EINVAL;
2016 goto exit;
2017 }
2018 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2019 numChannels);
2020 if (eHAL_STATUS_SUCCESS != status)
2021 {
2022 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2023 "%s: Failed to update channel list information", __func__);
2024 ret = -EINVAL;
2025 goto exit;
2026 }
2027 }
2028 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2029 {
2030 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2031 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002032 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002033 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002034 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002035
2036 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2037 ChannelList, &numChannels ))
2038 {
2039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2040 "%s: failed to get roam scan channel list", __func__);
2041 ret = -EFAULT;
2042 goto exit;
2043 }
2044 /* output channel list is of the format
2045 [Number of roam scan channels][Channel1][Channel2]... */
2046 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002047 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002048 for (j = 0; (j < numChannels); j++)
2049 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002050 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2051 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002052 }
2053
2054 if (copy_to_user(priv_data.buf, &extra, len + 1))
2055 {
2056 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2057 "%s: failed to copy data to user buffer", __func__);
2058 ret = -EFAULT;
2059 goto exit;
2060 }
2061 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002062 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2063 {
2064 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2065 char extra[32];
2066 tANI_U8 len = 0;
2067
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002068 /* Check if the features OKC/CCX/11R are supported simultaneously,
2069 then this operation is not permitted (return FAILURE) */
2070 if (ccxMode &&
2071 hdd_is_okc_mode_enabled(pHddCtx) &&
2072 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2073 {
2074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2075 "%s: OKC/CCX/11R are supported simultaneously"
2076 " hence this operation is not permitted!", __func__);
2077 ret = -EPERM;
2078 goto exit;
2079 }
2080
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002081 len = scnprintf(extra, sizeof(extra), "%s %d",
2082 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002083 if (copy_to_user(priv_data.buf, &extra, len + 1))
2084 {
2085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2086 "%s: failed to copy data to user buffer", __func__);
2087 ret = -EFAULT;
2088 goto exit;
2089 }
2090 }
2091 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2092 {
2093 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2094 char extra[32];
2095 tANI_U8 len = 0;
2096
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002097 /* Check if the features OKC/CCX/11R are supported simultaneously,
2098 then this operation is not permitted (return FAILURE) */
2099 if (okcMode &&
2100 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2101 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2102 {
2103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2104 "%s: OKC/CCX/11R are supported simultaneously"
2105 " hence this operation is not permitted!", __func__);
2106 ret = -EPERM;
2107 goto exit;
2108 }
2109
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002110 len = scnprintf(extra, sizeof(extra), "%s %d",
2111 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002112 if (copy_to_user(priv_data.buf, &extra, len + 1))
2113 {
2114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2115 "%s: failed to copy data to user buffer", __func__);
2116 ret = -EFAULT;
2117 goto exit;
2118 }
2119 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002120 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002121 {
2122 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2123 char extra[32];
2124 tANI_U8 len = 0;
2125
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002126 len = scnprintf(extra, sizeof(extra), "%s %d",
2127 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002128 if (copy_to_user(priv_data.buf, &extra, len + 1))
2129 {
2130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2131 "%s: failed to copy data to user buffer", __func__);
2132 ret = -EFAULT;
2133 goto exit;
2134 }
2135 }
2136 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2137 {
2138 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2139 char extra[32];
2140 tANI_U8 len = 0;
2141
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002142 len = scnprintf(extra, sizeof(extra), "%s %d",
2143 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002144 if (copy_to_user(priv_data.buf, &extra, len + 1))
2145 {
2146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2147 "%s: failed to copy data to user buffer", __func__);
2148 ret = -EFAULT;
2149 goto exit;
2150 }
2151 }
2152 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2153 {
2154 tANI_U8 *value = command;
2155 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2156
2157 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2158 value = value + 26;
2159 /* Convert the value from ascii to integer */
2160 ret = kstrtou8(value, 10, &minTime);
2161 if (ret < 0)
2162 {
2163 /* If the input value is greater than max value of datatype, then also
2164 kstrtou8 fails */
2165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2166 "%s: kstrtou8 failed range [%d - %d]", __func__,
2167 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2168 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2169 ret = -EINVAL;
2170 goto exit;
2171 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002172 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2173 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2174 {
2175 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2176 "scan min channel time value %d is out of range"
2177 " (Min: %d Max: %d)", minTime,
2178 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2179 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2180 ret = -EINVAL;
2181 goto exit;
2182 }
2183
2184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2185 "%s: Received Command to change channel min time = %d", __func__, minTime);
2186
2187 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2188 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2189 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002190 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2191 {
2192 tANI_U8 *value = command;
2193 tANI_U8 channel = 0;
2194 tANI_U8 dwellTime = 0;
2195 tANI_U8 bufLen = 0;
2196 tANI_U8 *buf = NULL;
2197 tSirMacAddr targetApBssid;
2198 eHalStatus status = eHAL_STATUS_SUCCESS;
2199 struct ieee80211_channel chan;
2200 tANI_U8 finalLen = 0;
2201 tANI_U8 *finalBuf = NULL;
2202 tANI_U8 temp = 0;
2203 u64 cookie;
2204 hdd_station_ctx_t *pHddStaCtx = NULL;
2205 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2206
2207 /* if not associated, no need to send action frame */
2208 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2209 {
2210 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2211 ret = -EINVAL;
2212 goto exit;
2213 }
2214
2215 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2216 &dwellTime, &buf, &bufLen);
2217 if (eHAL_STATUS_SUCCESS != status)
2218 {
2219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2220 "%s: Failed to parse send action frame data", __func__);
2221 ret = -EINVAL;
2222 goto exit;
2223 }
2224
2225 /* if the target bssid is different from currently associated AP,
2226 then no need to send action frame */
2227 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2228 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2229 {
2230 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2231 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002232 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002233 goto exit;
2234 }
2235
2236 /* if the channel number is different from operating channel then
2237 no need to send action frame */
2238 if (channel != pHddStaCtx->conn_info.operationChannel)
2239 {
2240 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2241 "%s: channel(%d) is different from operating channel(%d)",
2242 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2243 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002244 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002245 goto exit;
2246 }
2247 chan.center_freq = sme_ChnToFreq(channel);
2248
2249 finalLen = bufLen + 24;
2250 finalBuf = vos_mem_malloc(finalLen);
2251 if (NULL == finalBuf)
2252 {
2253 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2254 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002255 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002256 goto exit;
2257 }
2258 vos_mem_zero(finalBuf, finalLen);
2259
2260 /* Fill subtype */
2261 temp = SIR_MAC_MGMT_ACTION << 4;
2262 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2263
2264 /* Fill type */
2265 temp = SIR_MAC_MGMT_FRAME;
2266 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2267
2268 /* Fill destination address (bssid of the AP) */
2269 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2270
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002271 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002272 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2273
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002274 /* Fill BSSID (AP mac address) */
2275 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002276
2277 /* Fill received buffer from 24th address */
2278 vos_mem_copy(finalBuf + 24, buf, bufLen);
2279
Jeff Johnson11c33152013-04-16 17:52:40 -07002280 /* done with the parsed buffer */
2281 vos_mem_free(buf);
2282
Yue Maf49ba872013-08-19 12:04:25 -07002283 wlan_hdd_action( NULL,
2284#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2285 &(pAdapter->wdev),
2286#else
2287 dev,
2288#endif
2289 &chan, 0,
2290#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2291 NL80211_CHAN_HT20, 1,
2292#endif
2293 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002294 1, &cookie );
2295 vos_mem_free(finalBuf);
2296 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002297 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2298 {
2299 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2300 char extra[32];
2301 tANI_U8 len = 0;
2302
2303 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002304 len = scnprintf(extra, sizeof(extra), "%s %d",
2305 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002306 if (copy_to_user(priv_data.buf, &extra, len + 1))
2307 {
2308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2309 "%s: failed to copy data to user buffer", __func__);
2310 ret = -EFAULT;
2311 goto exit;
2312 }
2313 }
2314 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2315 {
2316 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002317 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002318 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002319
2320 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2321 value = value + 19;
2322 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002323 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002324 if (ret < 0)
2325 {
2326 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002327 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002328 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002329 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002330 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2331 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2332 ret = -EINVAL;
2333 goto exit;
2334 }
2335
2336 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2337 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2338 {
2339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2340 "lfr mode value %d is out of range"
2341 " (Min: %d Max: %d)", maxTime,
2342 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2343 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2344 ret = -EINVAL;
2345 goto exit;
2346 }
2347
2348 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2349 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2350
2351 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002352
2353 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2354 * where RFS is the RF Switching time. It is twice RFS to consider the
2355 * time to go off channel and return to the home channel. */
2356 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2357 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2358 {
2359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2360 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
2361 " Hence enforcing home away time to disable (0)",
2362 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2363 homeAwayTime = 0;
2364 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2365 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2366 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002367 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2368 }
2369 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2370 {
2371 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2372 char extra[32];
2373 tANI_U8 len = 0;
2374
2375 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002376 len = scnprintf(extra, sizeof(extra), "%s %d",
2377 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002378 if (copy_to_user(priv_data.buf, &extra, len + 1))
2379 {
2380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2381 "%s: failed to copy data to user buffer", __func__);
2382 ret = -EFAULT;
2383 goto exit;
2384 }
2385 }
2386 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2387 {
2388 tANI_U8 *value = command;
2389 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2390
2391 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2392 value = value + 16;
2393 /* Convert the value from ascii to integer */
2394 ret = kstrtou16(value, 10, &val);
2395 if (ret < 0)
2396 {
2397 /* If the input value is greater than max value of datatype, then also
2398 kstrtou16 fails */
2399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2400 "%s: kstrtou16 failed range [%d - %d]", __func__,
2401 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2402 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2403 ret = -EINVAL;
2404 goto exit;
2405 }
2406
2407 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2408 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2409 {
2410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2411 "scan home time value %d is out of range"
2412 " (Min: %d Max: %d)", val,
2413 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2414 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2415 ret = -EINVAL;
2416 goto exit;
2417 }
2418
2419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2420 "%s: Received Command to change scan home time = %d", __func__, val);
2421
2422 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2423 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2424 }
2425 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2426 {
2427 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2428 char extra[32];
2429 tANI_U8 len = 0;
2430
2431 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002432 len = scnprintf(extra, sizeof(extra), "%s %d",
2433 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002434 if (copy_to_user(priv_data.buf, &extra, len + 1))
2435 {
2436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2437 "%s: failed to copy data to user buffer", __func__);
2438 ret = -EFAULT;
2439 goto exit;
2440 }
2441 }
2442 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2443 {
2444 tANI_U8 *value = command;
2445 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2446
2447 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2448 value = value + 17;
2449 /* Convert the value from ascii to integer */
2450 ret = kstrtou8(value, 10, &val);
2451 if (ret < 0)
2452 {
2453 /* If the input value is greater than max value of datatype, then also
2454 kstrtou8 fails */
2455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2456 "%s: kstrtou8 failed range [%d - %d]", __func__,
2457 CFG_ROAM_INTRA_BAND_MIN,
2458 CFG_ROAM_INTRA_BAND_MAX);
2459 ret = -EINVAL;
2460 goto exit;
2461 }
2462
2463 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2464 (val > CFG_ROAM_INTRA_BAND_MAX))
2465 {
2466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2467 "intra band mode value %d is out of range"
2468 " (Min: %d Max: %d)", val,
2469 CFG_ROAM_INTRA_BAND_MIN,
2470 CFG_ROAM_INTRA_BAND_MAX);
2471 ret = -EINVAL;
2472 goto exit;
2473 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2475 "%s: Received Command to change intra band = %d", __func__, val);
2476
2477 pHddCtx->cfg_ini->nRoamIntraBand = val;
2478 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2479 }
2480 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2481 {
2482 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2483 char extra[32];
2484 tANI_U8 len = 0;
2485
2486 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002487 len = scnprintf(extra, sizeof(extra), "%s %d",
2488 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002489 if (copy_to_user(priv_data.buf, &extra, len + 1))
2490 {
2491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2492 "%s: failed to copy data to user buffer", __func__);
2493 ret = -EFAULT;
2494 goto exit;
2495 }
2496 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002497 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2498 {
2499 tANI_U8 *value = command;
2500 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2501
2502 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2503 value = value + 15;
2504 /* Convert the value from ascii to integer */
2505 ret = kstrtou8(value, 10, &nProbes);
2506 if (ret < 0)
2507 {
2508 /* If the input value is greater than max value of datatype, then also
2509 kstrtou8 fails */
2510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2511 "%s: kstrtou8 failed range [%d - %d]", __func__,
2512 CFG_ROAM_SCAN_N_PROBES_MIN,
2513 CFG_ROAM_SCAN_N_PROBES_MAX);
2514 ret = -EINVAL;
2515 goto exit;
2516 }
2517
2518 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2519 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2520 {
2521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2522 "NProbes value %d is out of range"
2523 " (Min: %d Max: %d)", nProbes,
2524 CFG_ROAM_SCAN_N_PROBES_MIN,
2525 CFG_ROAM_SCAN_N_PROBES_MAX);
2526 ret = -EINVAL;
2527 goto exit;
2528 }
2529
2530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2531 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2532
2533 pHddCtx->cfg_ini->nProbes = nProbes;
2534 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2535 }
2536 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2537 {
2538 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2539 char extra[32];
2540 tANI_U8 len = 0;
2541
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002542 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002543 if (copy_to_user(priv_data.buf, &extra, len + 1))
2544 {
2545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2546 "%s: failed to copy data to user buffer", __func__);
2547 ret = -EFAULT;
2548 goto exit;
2549 }
2550 }
2551 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2552 {
2553 tANI_U8 *value = command;
2554 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002555 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002556
2557 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2558 /* input value is in units of msec */
2559 value = value + 20;
2560 /* Convert the value from ascii to integer */
2561 ret = kstrtou16(value, 10, &homeAwayTime);
2562 if (ret < 0)
2563 {
2564 /* If the input value is greater than max value of datatype, then also
2565 kstrtou8 fails */
2566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2567 "%s: kstrtou8 failed range [%d - %d]", __func__,
2568 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2569 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2570 ret = -EINVAL;
2571 goto exit;
2572 }
2573
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002574 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2575 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2576 {
2577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2578 "homeAwayTime value %d is out of range"
2579 " (Min: %d Max: %d)", homeAwayTime,
2580 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2581 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2582 ret = -EINVAL;
2583 goto exit;
2584 }
2585
2586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2587 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2588
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002589 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2590 * where RFS is the RF Switching time. It is twice RFS to consider the
2591 * time to go off channel and return to the home channel. */
2592 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2593 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2594 {
2595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2596 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
2597 " Hence enforcing home away time to disable (0)",
2598 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2599 homeAwayTime = 0;
2600 }
2601
2602 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2603 {
2604 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2605 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2606 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002607 }
2608 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2609 {
2610 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2611 char extra[32];
2612 tANI_U8 len = 0;
2613
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002614 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002615 if (copy_to_user(priv_data.buf, &extra, len + 1))
2616 {
2617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2618 "%s: failed to copy data to user buffer", __func__);
2619 ret = -EFAULT;
2620 goto exit;
2621 }
2622 }
2623 else if (strncmp(command, "REASSOC", 7) == 0)
2624 {
2625 tANI_U8 *value = command;
2626 tANI_U8 channel = 0;
2627 tSirMacAddr targetApBssid;
2628 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002629#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2630 tCsrHandoffRequest handoffInfo;
2631#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002632 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002633 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2634
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002635 /* if not associated, no need to proceed with reassoc */
2636 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2637 {
2638 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2639 ret = -EINVAL;
2640 goto exit;
2641 }
2642
2643 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2644 if (eHAL_STATUS_SUCCESS != status)
2645 {
2646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2647 "%s: Failed to parse reassoc command data", __func__);
2648 ret = -EINVAL;
2649 goto exit;
2650 }
2651
2652 /* if the target bssid is same as currently associated AP,
2653 then no need to proceed with reassoc */
2654 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2655 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2656 {
2657 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2658 ret = -EINVAL;
2659 goto exit;
2660 }
2661
2662 /* Check channel number is a valid channel number */
2663 if(VOS_STATUS_SUCCESS !=
2664 wlan_hdd_validate_operation_channel(pAdapter, channel))
2665 {
2666 hddLog(VOS_TRACE_LEVEL_ERROR,
2667 "%s: Invalid Channel [%d] \n", __func__, channel);
2668 return -EINVAL;
2669 }
2670
2671 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002672#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2673 handoffInfo.channel = channel;
2674 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2675 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2676#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002677 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002678#endif
2679#ifdef FEATURE_WLAN_LFR
2680 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2681 {
2682 tANI_U8 *value = command;
2683 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2684
2685 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2686 value = value + 12;
2687 /* Convert the value from ascii to integer */
2688 ret = kstrtou8(value, 10, &lfrMode);
2689 if (ret < 0)
2690 {
2691 /* If the input value is greater than max value of datatype, then also
2692 kstrtou8 fails */
2693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2694 "%s: kstrtou8 failed range [%d - %d]", __func__,
2695 CFG_LFR_FEATURE_ENABLED_MIN,
2696 CFG_LFR_FEATURE_ENABLED_MAX);
2697 ret = -EINVAL;
2698 goto exit;
2699 }
2700
2701 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2702 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2703 {
2704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2705 "lfr mode value %d is out of range"
2706 " (Min: %d Max: %d)", lfrMode,
2707 CFG_LFR_FEATURE_ENABLED_MIN,
2708 CFG_LFR_FEATURE_ENABLED_MAX);
2709 ret = -EINVAL;
2710 goto exit;
2711 }
2712
2713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2714 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2715
2716 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2717 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2718 }
2719#endif
2720#ifdef WLAN_FEATURE_VOWIFI_11R
2721 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2722 {
2723 tANI_U8 *value = command;
2724 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2725
2726 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2727 value = value + 18;
2728 /* Convert the value from ascii to integer */
2729 ret = kstrtou8(value, 10, &ft);
2730 if (ret < 0)
2731 {
2732 /* If the input value is greater than max value of datatype, then also
2733 kstrtou8 fails */
2734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2735 "%s: kstrtou8 failed range [%d - %d]", __func__,
2736 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2737 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2738 ret = -EINVAL;
2739 goto exit;
2740 }
2741
2742 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2743 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2744 {
2745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2746 "ft mode value %d is out of range"
2747 " (Min: %d Max: %d)", ft,
2748 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2749 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2750 ret = -EINVAL;
2751 goto exit;
2752 }
2753
2754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2755 "%s: Received Command to change ft mode = %d", __func__, ft);
2756
2757 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2758 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2759 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302760
2761 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2762 {
2763 tANI_U8 *value = command;
2764 tSirMacAddr targetApBssid;
2765 tANI_U8 trigger = 0;
2766 eHalStatus status = eHAL_STATUS_SUCCESS;
2767 hdd_station_ctx_t *pHddStaCtx = NULL;
2768 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2769
2770 /* if not associated, no need to proceed with reassoc */
2771 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2772 {
2773 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2774 ret = -EINVAL;
2775 goto exit;
2776 }
2777
2778 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2779 if (eHAL_STATUS_SUCCESS != status)
2780 {
2781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2782 "%s: Failed to parse reassoc command data", __func__);
2783 ret = -EINVAL;
2784 goto exit;
2785 }
2786
2787 /* if the target bssid is same as currently associated AP,
2788 then no need to proceed with reassoc */
2789 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2790 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2791 {
2792 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2793 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2794 __func__);
2795 ret = -EINVAL;
2796 goto exit;
2797 }
2798
2799 /* Proceed with scan/roam */
2800 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2801 &targetApBssid[0],
2802 (tSmeFastRoamTrigger)(trigger));
2803 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002804#endif
2805#ifdef FEATURE_WLAN_CCX
2806 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2807 {
2808 tANI_U8 *value = command;
2809 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2810
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002811 /* Check if the features OKC/CCX/11R are supported simultaneously,
2812 then this operation is not permitted (return FAILURE) */
2813 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2814 hdd_is_okc_mode_enabled(pHddCtx) &&
2815 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2816 {
2817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2818 "%s: OKC/CCX/11R are supported simultaneously"
2819 " hence this operation is not permitted!", __func__);
2820 ret = -EPERM;
2821 goto exit;
2822 }
2823
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002824 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2825 value = value + 11;
2826 /* Convert the value from ascii to integer */
2827 ret = kstrtou8(value, 10, &ccxMode);
2828 if (ret < 0)
2829 {
2830 /* If the input value is greater than max value of datatype, then also
2831 kstrtou8 fails */
2832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2833 "%s: kstrtou8 failed range [%d - %d]", __func__,
2834 CFG_CCX_FEATURE_ENABLED_MIN,
2835 CFG_CCX_FEATURE_ENABLED_MAX);
2836 ret = -EINVAL;
2837 goto exit;
2838 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002839 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2840 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2841 {
2842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2843 "Ccx mode value %d is out of range"
2844 " (Min: %d Max: %d)", ccxMode,
2845 CFG_CCX_FEATURE_ENABLED_MIN,
2846 CFG_CCX_FEATURE_ENABLED_MAX);
2847 ret = -EINVAL;
2848 goto exit;
2849 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002850 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2851 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
2852
2853 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
2854 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
2855 }
2856#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002857 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
2858 {
2859 tANI_U8 *value = command;
2860 tANI_BOOLEAN roamScanControl = 0;
2861
2862 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
2863 value = value + 19;
2864 /* Convert the value from ascii to integer */
2865 ret = kstrtou8(value, 10, &roamScanControl);
2866 if (ret < 0)
2867 {
2868 /* If the input value is greater than max value of datatype, then also
2869 kstrtou8 fails */
2870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2871 "%s: kstrtou8 failed ", __func__);
2872 ret = -EINVAL;
2873 goto exit;
2874 }
2875
2876 if (0 != roamScanControl)
2877 {
2878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2879 "roam scan control invalid value = %d",
2880 roamScanControl);
2881 ret = -EINVAL;
2882 goto exit;
2883 }
2884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2885 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
2886
2887 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
2888 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002889#ifdef FEATURE_WLAN_OKC
2890 else if (strncmp(command, "SETOKCMODE", 10) == 0)
2891 {
2892 tANI_U8 *value = command;
2893 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
2894
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002895 /* Check if the features OKC/CCX/11R are supported simultaneously,
2896 then this operation is not permitted (return FAILURE) */
2897 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2898 hdd_is_okc_mode_enabled(pHddCtx) &&
2899 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2900 {
2901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2902 "%s: OKC/CCX/11R are supported simultaneously"
2903 " hence this operation is not permitted!", __func__);
2904 ret = -EPERM;
2905 goto exit;
2906 }
2907
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002908 /* Move pointer to ahead of SETOKCMODE<delimiter> */
2909 value = value + 11;
2910 /* Convert the value from ascii to integer */
2911 ret = kstrtou8(value, 10, &okcMode);
2912 if (ret < 0)
2913 {
2914 /* If the input value is greater than max value of datatype, then also
2915 kstrtou8 fails */
2916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2917 "%s: kstrtou8 failed range [%d - %d]", __func__,
2918 CFG_OKC_FEATURE_ENABLED_MIN,
2919 CFG_OKC_FEATURE_ENABLED_MAX);
2920 ret = -EINVAL;
2921 goto exit;
2922 }
2923
2924 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
2925 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
2926 {
2927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2928 "Okc mode value %d is out of range"
2929 " (Min: %d Max: %d)", okcMode,
2930 CFG_OKC_FEATURE_ENABLED_MIN,
2931 CFG_OKC_FEATURE_ENABLED_MAX);
2932 ret = -EINVAL;
2933 goto exit;
2934 }
2935
2936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2937 "%s: Received Command to change okc mode = %d", __func__, okcMode);
2938
2939 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
2940 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002941 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
2942 {
2943 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
2944 char extra[32];
2945 tANI_U8 len = 0;
2946
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002947 len = scnprintf(extra, sizeof(extra), "%s %d",
2948 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002949 if (copy_to_user(priv_data.buf, &extra, len + 1))
2950 {
2951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2952 "%s: failed to copy data to user buffer", __func__);
2953 ret = -EFAULT;
2954 goto exit;
2955 }
2956 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002957#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302958#ifdef WLAN_FEATURE_PACKET_FILTERING
2959 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2960 {
2961 tANI_U8 filterType = 0;
2962 tANI_U8 *value = command;
2963
2964 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2965 value = value + 22;
2966
2967 /* Convert the value from ascii to integer */
2968 ret = kstrtou8(value, 10, &filterType);
2969 if (ret < 0)
2970 {
2971 /* If the input value is greater than max value of datatype,
2972 * then also kstrtou8 fails
2973 */
2974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2975 "%s: kstrtou8 failed range ", __func__);
2976 ret = -EINVAL;
2977 goto exit;
2978 }
2979
2980 if (filterType != 0 && filterType != 1)
2981 {
2982 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2983 "%s: Accepted Values are 0 and 1 ", __func__);
2984 ret = -EINVAL;
2985 goto exit;
2986 }
2987 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2988 pAdapter->sessionId);
2989 }
2990#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302991 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2992 {
2993 char *dhcpPhase;
2994 dhcpPhase = command + 12;
2995 if ('1' == *dhcpPhase)
2996 {
2997 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2998 pAdapter->macAddressCurrent.bytes);
2999 }
3000 else if ('2' == *dhcpPhase)
3001 {
3002 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3003 pAdapter->macAddressCurrent.bytes);
3004 }
3005 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003006 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3007 {
3008 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3009 }
3010 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3011 {
3012 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3013 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303014 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3015 {
3016 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3017 char extra[32];
3018 tANI_U8 len = 0;
3019
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003020 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303021 (int)pCfg->nActiveMaxChnTime);
3022 if (copy_to_user(priv_data.buf, &extra, len + 1))
3023 {
3024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3025 "%s: failed to copy data to user buffer", __func__);
3026 ret = -EFAULT;
3027 goto exit;
3028 }
3029 ret = len;
3030 }
3031 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3032 {
3033 tANI_U8 *value = command;
3034 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3035 int val = 0, temp;
3036
3037 value = value + 13;
3038 temp = kstrtou32(value, 10, &val);
3039 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3040 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3041 {
3042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3043 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3044 ret = -EFAULT;
3045 goto exit;
3046 }
3047 pCfg->nActiveMaxChnTime = val;
3048 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003049 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3050 {
3051 tANI_U8 filterType = 0;
3052 tANI_U8 *value;
3053 value = command + 9;
3054
3055 /* Convert the value from ascii to integer */
3056 ret = kstrtou8(value, 10, &filterType);
3057 if (ret < 0)
3058 {
3059 /* If the input value is greater than max value of datatype,
3060 * then also kstrtou8 fails
3061 */
3062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3063 "%s: kstrtou8 failed range ", __func__);
3064 ret = -EINVAL;
3065 goto exit;
3066 }
3067 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3068 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3069 {
3070 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3071 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3072 " 2-Sink ", __func__);
3073 ret = -EINVAL;
3074 goto exit;
3075 }
3076 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3077 pHddCtx->drvr_miracast = filterType;
3078 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3079 }
Leo Chang614d2072013-08-22 14:59:44 -07003080 else if (strncmp(command, "SETMCRATE", 9) == 0)
3081 {
3082 int rc;
3083 tANI_U8 *value = command;
3084 int targetRate;
3085
3086 /* Only valid for SAP mode */
3087 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3088 {
3089 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3090 "%s: SAP mode is not running", __func__);
3091 ret = -EFAULT;
3092 goto exit;
3093 }
3094
3095 /* Move pointer to ahead of SETMCRATE<delimiter> */
3096 /* input value is in units of hundred kbps */
3097 value = value + 10;
3098 /* Convert the value from ascii to integer, decimal base */
3099 ret = kstrtouint(value, 10, &targetRate);
3100
3101 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
3102 if (rc)
3103 {
3104 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3105 "%s: Set MC Rate Fail %d", __func__, rc);
3106 ret = -EFAULT;
3107 goto exit;
3108 }
3109 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303110#ifdef FEATURE_WLAN_BATCH_SCAN
3111 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3112 {
3113 char extra[32];
3114 tANI_U8 len = 0;
3115 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3116
3117 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3118 {
3119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3120 "%s: Batch scan feature is not supported by FW", __func__);
3121 ret = -EINVAL;
3122 goto exit;
3123 }
3124
3125 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3126 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3127 {
3128 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3129 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3130 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3131 " mode",
3132 pAdapter->device_mode);
3133 ret = -EINVAL;
3134 goto exit;
3135 }
3136
3137 len = snprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
3138 version);
3139 if (copy_to_user(priv_data.buf, &extra, len + 1))
3140 {
3141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3142 "%s: failed to copy data to user buffer", __func__);
3143 ret = -EFAULT;
3144 goto exit;
3145 }
3146 ret = HDD_BATCH_SCAN_VERSION;
3147 }
3148 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3149 {
3150 int status;
3151 tANI_U8 *value = (command + 16);
3152 eHalStatus halStatus;
3153 unsigned long rc;
3154 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3155 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3156
3157 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3158 {
3159 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3160 "%s: Batch scan feature is not supported by FW", __func__);
3161 ret = -EINVAL;
3162 goto exit;
3163 }
3164
3165 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3166 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3167 {
3168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3169 "Received WLS_BATCHING_SET command in invalid mode %d "
3170 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3171 pAdapter->device_mode);
3172 ret = -EINVAL;
3173 goto exit;
3174 }
3175
3176 status = hdd_parse_set_batchscan_command(value, pReq);
3177 if (status)
3178 {
3179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3180 "Invalid WLS_BATCHING_SET command");
3181 ret = -EINVAL;
3182 goto exit;
3183 }
3184 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3185 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3186 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3187 pAdapter);
3188
3189 if ( eHAL_STATUS_SUCCESS == halStatus )
3190 {
3191 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3192 "sme_SetBatchScanReq returned success halStatus %d",
3193 halStatus);
3194 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3195 {
3196 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3197 rc = wait_for_completion_timeout(
3198 &pAdapter->hdd_set_batch_scan_req_var,
3199 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3200 if (0 == rc)
3201 {
3202 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3203 "%s: Timeout waiting for set batch scan to complete",
3204 __func__);
3205 ret = -EINVAL;
3206 goto exit;
3207 }
3208 }
3209 if ( !pRsp->nScansToBatch )
3210 {
3211 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3212 "%s: Received set batch scan failure response from FW",
3213 __func__, pRsp->nScansToBatch);
3214 ret = -EINVAL;
3215 goto exit;
3216 }
3217 /*As per the Batch Scan Framework API we should return the MIN of
3218 either MSCAN or the max # of scans firmware can cache*/
3219 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3220
3221 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3222 "%s: request MSCAN %d response MSCAN %d ret %d",
3223 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3224 }
3225 else
3226 {
3227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3228 "sme_SetBatchScanReq returned failure halStatus %d",
3229 halStatus);
3230 ret = -EINVAL;
3231 goto exit;
3232 }
3233 }
3234 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3235 {
3236 eHalStatus halStatus;
3237 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3238 pInd->param = 0;
3239
3240 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3241 {
3242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3243 "%s: Batch scan feature is not supported by FW", __func__);
3244 ret = -EINVAL;
3245 goto exit;
3246 }
3247
3248 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3249 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3250 {
3251 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3252 "Received WLS_BATCHING_STOP command in invalid mode %d "
3253 "WLS_BATCHING_STOP is only allowed in infra STA/P2P client"
3254 " mode",
3255 pAdapter->device_mode);
3256 ret = -EINVAL;
3257 goto exit;
3258 }
3259
3260 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3261 pAdapter->sessionId);
3262 if ( eHAL_STATUS_SUCCESS == halStatus )
3263 {
3264 ret = 0;
3265 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3266 "sme_StopBatchScanInd returned success halStatus %d",
3267 halStatus);
3268 }
3269 else
3270 {
3271 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3272 "sme_StopBatchScanInd returned failure halStatus %d",
3273 halStatus);
3274 ret = -EINVAL;
3275 goto exit;
3276 }
3277 }
3278 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3279 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003280 tANI_U32 remain_len;
3281
Rajeev79dbe4c2013-10-05 11:03:42 +05303282 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3283 {
3284 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3285 "%s: Batch scan feature is not supported by FW", __func__);
3286 ret = -EINVAL;
3287 goto exit;
3288 }
3289
3290 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3291 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3292 {
3293 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3294 "Received WLS_BATCHING_GET command in invalid mode %d "
3295 "WLS_BATCHING_GET is only allowed in infra STA/P2P client"
3296 " mode",
3297 pAdapter->device_mode);
3298 ret = -EINVAL;
3299 goto exit;
3300 }
3301
3302 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003303 remain_len = priv_data.total_len - priv_data.used_len;
3304 if (remain_len < priv_data.total_len)
3305 {
3306 /*Clear previous batch scan response data if any*/
3307 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3308 }
3309 else
3310 {
3311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3312 "Invalid total length from user space can't fetch batch"
3313 " scan response total_len %ld used_len %ld remain len %ld",
3314 priv_data.total_len, priv_data.used_len, remain_len);
3315 ret = -EINVAL;
3316 goto exit;
3317 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303318 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3319 }
3320#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003321 else {
3322 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3323 __func__, command);
3324 }
3325
Jeff Johnson295189b2012-06-20 16:38:30 -07003326 }
3327exit:
3328 if (command)
3329 {
3330 kfree(command);
3331 }
3332 return ret;
3333}
3334
Srinivas Girigowdade697412013-02-14 16:31:48 -08003335#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3336void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3337{
3338 eCsrBand band = -1;
3339 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3340 switch (band)
3341 {
3342 case eCSR_BAND_ALL:
3343 *pBand = WLAN_HDD_UI_BAND_AUTO;
3344 break;
3345
3346 case eCSR_BAND_24:
3347 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3348 break;
3349
3350 case eCSR_BAND_5G:
3351 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3352 break;
3353
3354 default:
3355 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3356 *pBand = -1;
3357 break;
3358 }
3359}
3360
3361/**---------------------------------------------------------------------------
3362
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003363 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3364
3365 This function parses the send action frame data passed in the format
3366 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3367
Srinivas Girigowda56076852013-08-20 14:00:50 -07003368 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003369 \param - pTargetApBssid Pointer to target Ap bssid
3370 \param - pChannel Pointer to the Target AP channel
3371 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3372 \param - pBuf Pointer to data
3373 \param - pBufLen Pointer to data length
3374
3375 \return - 0 for success non-zero for failure
3376
3377 --------------------------------------------------------------------------*/
3378VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3379 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3380{
3381 tANI_U8 *inPtr = pValue;
3382 tANI_U8 *dataEnd;
3383 int tempInt;
3384 int j = 0;
3385 int i = 0;
3386 int v = 0;
3387 tANI_U8 tempBuf[32];
3388 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003389 /* 12 hexa decimal digits and 5 ':' */
3390 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003391
3392 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3393 /*no argument after the command*/
3394 if (NULL == inPtr)
3395 {
3396 return -EINVAL;
3397 }
3398
3399 /*no space after the command*/
3400 else if (SPACE_ASCII_VALUE != *inPtr)
3401 {
3402 return -EINVAL;
3403 }
3404
3405 /*removing empty spaces*/
3406 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3407
3408 /*no argument followed by spaces*/
3409 if ('\0' == *inPtr)
3410 {
3411 return -EINVAL;
3412 }
3413
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003414 v = sscanf(inPtr, "%17s", macAddress);
3415 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003416 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003417 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3418 "Invalid MAC address or All hex inputs are not read (%d)", v);
3419 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003420 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003421
3422 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3423 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3424 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3425 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3426 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3427 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003428
3429 /* point to the next argument */
3430 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3431 /*no argument after the command*/
3432 if (NULL == inPtr) return -EINVAL;
3433
3434 /*removing empty spaces*/
3435 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3436
3437 /*no argument followed by spaces*/
3438 if ('\0' == *inPtr)
3439 {
3440 return -EINVAL;
3441 }
3442
3443 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003444 v = sscanf(inPtr, "%32s ", tempBuf);
3445 if (1 != v) return -EINVAL;
3446
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003447 v = kstrtos32(tempBuf, 10, &tempInt);
3448 if ( v < 0) return -EINVAL;
3449
3450 *pChannel = tempInt;
3451
3452 /* point to the next argument */
3453 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3454 /*no argument after the command*/
3455 if (NULL == inPtr) return -EINVAL;
3456 /*removing empty spaces*/
3457 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3458
3459 /*no argument followed by spaces*/
3460 if ('\0' == *inPtr)
3461 {
3462 return -EINVAL;
3463 }
3464
3465 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003466 v = sscanf(inPtr, "%32s ", tempBuf);
3467 if (1 != v) return -EINVAL;
3468
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003469 v = kstrtos32(tempBuf, 10, &tempInt);
3470 if ( v < 0) return -EINVAL;
3471
3472 *pDwellTime = tempInt;
3473
3474 /* point to the next argument */
3475 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3476 /*no argument after the command*/
3477 if (NULL == inPtr) return -EINVAL;
3478 /*removing empty spaces*/
3479 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3480
3481 /*no argument followed by spaces*/
3482 if ('\0' == *inPtr)
3483 {
3484 return -EINVAL;
3485 }
3486
3487 /* find the length of data */
3488 dataEnd = inPtr;
3489 while(('\0' != *dataEnd) )
3490 {
3491 dataEnd++;
3492 ++(*pBufLen);
3493 }
3494 if ( *pBufLen <= 0) return -EINVAL;
3495
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07003496 /* Allocate the number of bytes based on the number of input characters
3497 whether it is even or odd.
3498 if the number of input characters are even, then we need N/2 byte.
3499 if the number of input characters are odd, then we need do (N+1)/2 to
3500 compensate rounding off.
3501 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
3502 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
3503 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003504 if (NULL == *pBuf)
3505 {
3506 hddLog(VOS_TRACE_LEVEL_FATAL,
3507 "%s: vos_mem_alloc failed ", __func__);
3508 return -EINVAL;
3509 }
3510
3511 /* the buffer received from the upper layer is character buffer,
3512 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
3513 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
3514 and f0 in 3rd location */
3515 for (i = 0, j = 0; j < *pBufLen; j += 2)
3516 {
3517 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
3518 (*pBuf)[i++] = tempByte;
3519 }
3520 *pBufLen = i;
3521 return VOS_STATUS_SUCCESS;
3522}
3523
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003524/**---------------------------------------------------------------------------
3525
Srinivas Girigowdade697412013-02-14 16:31:48 -08003526 \brief hdd_parse_channellist() - HDD Parse channel list
3527
3528 This function parses the channel list passed in the format
3529 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003530 if the Number of channels (N) does not match with the actual number of channels passed
3531 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
3532 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
3533 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
3534 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08003535
3536 \param - pValue Pointer to input channel list
3537 \param - ChannelList Pointer to local output array to record channel list
3538 \param - pNumChannels Pointer to number of roam scan channels
3539
3540 \return - 0 for success non-zero for failure
3541
3542 --------------------------------------------------------------------------*/
3543VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
3544{
3545 tANI_U8 *inPtr = pValue;
3546 int tempInt;
3547 int j = 0;
3548 int v = 0;
3549 char buf[32];
3550
3551 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3552 /*no argument after the command*/
3553 if (NULL == inPtr)
3554 {
3555 return -EINVAL;
3556 }
3557
3558 /*no space after the command*/
3559 else if (SPACE_ASCII_VALUE != *inPtr)
3560 {
3561 return -EINVAL;
3562 }
3563
3564 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003565 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003566
3567 /*no argument followed by spaces*/
3568 if ('\0' == *inPtr)
3569 {
3570 return -EINVAL;
3571 }
3572
3573 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003574 v = sscanf(inPtr, "%32s ", buf);
3575 if (1 != v) return -EINVAL;
3576
Srinivas Girigowdade697412013-02-14 16:31:48 -08003577 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003578 if ((v < 0) ||
3579 (tempInt <= 0) ||
3580 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
3581 {
3582 return -EINVAL;
3583 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003584
3585 *pNumChannels = tempInt;
3586
3587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3588 "Number of channels are: %d", *pNumChannels);
3589
3590 for (j = 0; j < (*pNumChannels); j++)
3591 {
3592 /*inPtr pointing to the beginning of first space after number of channels*/
3593 inPtr = strpbrk( inPtr, " " );
3594 /*no channel list after the number of channels argument*/
3595 if (NULL == inPtr)
3596 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003597 if (0 != j)
3598 {
3599 *pNumChannels = j;
3600 return VOS_STATUS_SUCCESS;
3601 }
3602 else
3603 {
3604 return -EINVAL;
3605 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003606 }
3607
3608 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003609 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003610
3611 /*no channel list after the number of channels argument and spaces*/
3612 if ( '\0' == *inPtr )
3613 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003614 if (0 != j)
3615 {
3616 *pNumChannels = j;
3617 return VOS_STATUS_SUCCESS;
3618 }
3619 else
3620 {
3621 return -EINVAL;
3622 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003623 }
3624
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003625 v = sscanf(inPtr, "%32s ", buf);
3626 if (1 != v) return -EINVAL;
3627
Srinivas Girigowdade697412013-02-14 16:31:48 -08003628 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003629 if ((v < 0) ||
3630 (tempInt <= 0) ||
3631 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3632 {
3633 return -EINVAL;
3634 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003635 pChannelList[j] = tempInt;
3636
3637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3638 "Channel %d added to preferred channel list",
3639 pChannelList[j] );
3640 }
3641
Srinivas Girigowdade697412013-02-14 16:31:48 -08003642 return VOS_STATUS_SUCCESS;
3643}
3644
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003645
3646/**---------------------------------------------------------------------------
3647
3648 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
3649
3650 This function parses the reasoc command data passed in the format
3651 REASSOC<space><bssid><space><channel>
3652
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003653 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003654 \param - pTargetApBssid Pointer to target Ap bssid
3655 \param - pChannel Pointer to the Target AP channel
3656
3657 \return - 0 for success non-zero for failure
3658
3659 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003660VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
3661 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003662{
3663 tANI_U8 *inPtr = pValue;
3664 int tempInt;
3665 int v = 0;
3666 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003667 /* 12 hexa decimal digits and 5 ':' */
3668 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003669
3670 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3671 /*no argument after the command*/
3672 if (NULL == inPtr)
3673 {
3674 return -EINVAL;
3675 }
3676
3677 /*no space after the command*/
3678 else if (SPACE_ASCII_VALUE != *inPtr)
3679 {
3680 return -EINVAL;
3681 }
3682
3683 /*removing empty spaces*/
3684 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3685
3686 /*no argument followed by spaces*/
3687 if ('\0' == *inPtr)
3688 {
3689 return -EINVAL;
3690 }
3691
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003692 v = sscanf(inPtr, "%17s", macAddress);
3693 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003694 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3696 "Invalid MAC address or All hex inputs are not read (%d)", v);
3697 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003698 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003699
3700 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3701 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3702 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3703 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3704 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3705 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003706
3707 /* point to the next argument */
3708 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3709 /*no argument after the command*/
3710 if (NULL == inPtr) return -EINVAL;
3711
3712 /*removing empty spaces*/
3713 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3714
3715 /*no argument followed by spaces*/
3716 if ('\0' == *inPtr)
3717 {
3718 return -EINVAL;
3719 }
3720
3721 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003722 v = sscanf(inPtr, "%32s ", tempBuf);
3723 if (1 != v) return -EINVAL;
3724
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003725 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003726 if ((v < 0) ||
3727 (tempInt <= 0) ||
3728 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3729 {
3730 return -EINVAL;
3731 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003732
3733 *pChannel = tempInt;
3734 return VOS_STATUS_SUCCESS;
3735}
3736
3737#endif
3738
Jeff Johnson295189b2012-06-20 16:38:30 -07003739/**---------------------------------------------------------------------------
3740
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003741 \brief hdd_is_valid_mac_address() - Validate MAC address
3742
3743 This function validates whether the given MAC address is valid or not
3744 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
3745 where X is the hexa decimal digit character and separated by ':'
3746 This algorithm works even if MAC address is not separated by ':'
3747
3748 This code checks given input string mac contains exactly 12 hexadecimal digits.
3749 and a separator colon : appears in the input string only after
3750 an even number of hex digits.
3751
3752 \param - pMacAddr pointer to the input MAC address
3753 \return - 1 for valid and 0 for invalid
3754
3755 --------------------------------------------------------------------------*/
3756
3757v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
3758{
3759 int xdigit = 0;
3760 int separator = 0;
3761 while (*pMacAddr)
3762 {
3763 if (isxdigit(*pMacAddr))
3764 {
3765 xdigit++;
3766 }
3767 else if (':' == *pMacAddr)
3768 {
3769 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
3770 break;
3771
3772 ++separator;
3773 }
3774 else
3775 {
3776 separator = -1;
3777 /* Invalid MAC found */
3778 return 0;
3779 }
3780 ++pMacAddr;
3781 }
3782 return (xdigit == 12 && (separator == 5 || separator == 0));
3783}
3784
3785/**---------------------------------------------------------------------------
3786
Jeff Johnson295189b2012-06-20 16:38:30 -07003787 \brief hdd_open() - HDD Open function
3788
3789 This is called in response to ifconfig up
3790
3791 \param - dev Pointer to net_device structure
3792
3793 \return - 0 for success non-zero for failure
3794
3795 --------------------------------------------------------------------------*/
3796int hdd_open (struct net_device *dev)
3797{
3798 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3799 hdd_context_t *pHddCtx;
3800 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3801 VOS_STATUS status;
3802 v_BOOL_t in_standby = TRUE;
3803
3804 if (NULL == pAdapter)
3805 {
3806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003807 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003808 return -ENODEV;
3809 }
3810
3811 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3812 if (NULL == pHddCtx)
3813 {
3814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003815 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003816 return -ENODEV;
3817 }
3818
3819 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3820 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
3821 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003822 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
3823 {
3824 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05303825 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003826 in_standby = FALSE;
3827 break;
3828 }
3829 else
3830 {
3831 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3832 pAdapterNode = pNext;
3833 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003834 }
3835
3836 if (TRUE == in_standby)
3837 {
3838 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
3839 {
3840 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
3841 "wlan out of power save", __func__);
3842 return -EINVAL;
3843 }
3844 }
3845
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003846 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07003847 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3848 {
3849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003850 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003851 /* Enable TX queues only when we are connected */
3852 netif_tx_start_all_queues(dev);
3853 }
3854
3855 return 0;
3856}
3857
3858int hdd_mon_open (struct net_device *dev)
3859{
3860 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3861
3862 if(pAdapter == NULL) {
3863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003864 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003865 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003866 }
3867
3868 netif_start_queue(dev);
3869
3870 return 0;
3871}
3872/**---------------------------------------------------------------------------
3873
3874 \brief hdd_stop() - HDD stop function
3875
3876 This is called in response to ifconfig down
3877
3878 \param - dev Pointer to net_device structure
3879
3880 \return - 0 for success non-zero for failure
3881
3882 --------------------------------------------------------------------------*/
3883
3884int hdd_stop (struct net_device *dev)
3885{
3886 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3887 hdd_context_t *pHddCtx;
3888 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3889 VOS_STATUS status;
3890 v_BOOL_t enter_standby = TRUE;
3891
3892 ENTER();
3893
3894 if (NULL == pAdapter)
3895 {
3896 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003897 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003898 return -ENODEV;
3899 }
3900
3901 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3902 if (NULL == pHddCtx)
3903 {
3904 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003905 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003906 return -ENODEV;
3907 }
3908
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003909 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07003910 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
3911 netif_tx_disable(pAdapter->dev);
3912 netif_carrier_off(pAdapter->dev);
3913
3914
3915 /* SoftAP ifaces should never go in power save mode
3916 making sure same here. */
3917 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
3918 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07003919 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07003920 )
3921 {
3922 /* SoftAP mode, so return from here */
3923 EXIT();
3924 return 0;
3925 }
3926
3927 /* Find if any iface is up then
3928 if any iface is up then can't put device to sleep/ power save mode. */
3929 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3930 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
3931 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003932 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
3933 {
3934 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05303935 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003936 enter_standby = FALSE;
3937 break;
3938 }
3939 else
3940 {
3941 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3942 pAdapterNode = pNext;
3943 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003944 }
3945
3946 if (TRUE == enter_standby)
3947 {
3948 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
3949 "entering standby", __func__);
3950 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
3951 {
3952 /*log and return success*/
3953 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
3954 "wlan in power save", __func__);
3955 }
3956 }
3957
3958 EXIT();
3959 return 0;
3960}
3961
3962/**---------------------------------------------------------------------------
3963
3964 \brief hdd_uninit() - HDD uninit function
3965
3966 This is called during the netdev unregister to uninitialize all data
3967associated with the device
3968
3969 \param - dev Pointer to net_device structure
3970
3971 \return - void
3972
3973 --------------------------------------------------------------------------*/
3974static void hdd_uninit (struct net_device *dev)
3975{
3976 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3977
3978 ENTER();
3979
3980 do
3981 {
3982 if (NULL == pAdapter)
3983 {
3984 hddLog(VOS_TRACE_LEVEL_FATAL,
3985 "%s: NULL pAdapter", __func__);
3986 break;
3987 }
3988
3989 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3990 {
3991 hddLog(VOS_TRACE_LEVEL_FATAL,
3992 "%s: Invalid magic", __func__);
3993 break;
3994 }
3995
3996 if (NULL == pAdapter->pHddCtx)
3997 {
3998 hddLog(VOS_TRACE_LEVEL_FATAL,
3999 "%s: NULL pHddCtx", __func__);
4000 break;
4001 }
4002
4003 if (dev != pAdapter->dev)
4004 {
4005 hddLog(VOS_TRACE_LEVEL_FATAL,
4006 "%s: Invalid device reference", __func__);
4007 /* we haven't validated all cases so let this go for now */
4008 }
4009
4010 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4011
4012 /* after uninit our adapter structure will no longer be valid */
4013 pAdapter->dev = NULL;
4014 pAdapter->magic = 0;
4015 } while (0);
4016
4017 EXIT();
4018}
4019
4020/**---------------------------------------------------------------------------
4021
4022 \brief hdd_release_firmware() -
4023
4024 This function calls the release firmware API to free the firmware buffer.
4025
4026 \param - pFileName Pointer to the File Name.
4027 pCtx - Pointer to the adapter .
4028
4029
4030 \return - 0 for success, non zero for failure
4031
4032 --------------------------------------------------------------------------*/
4033
4034VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4035{
4036 VOS_STATUS status = VOS_STATUS_SUCCESS;
4037 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4038 ENTER();
4039
4040
4041 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4042
4043 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4044
4045 if(pHddCtx->fw) {
4046 release_firmware(pHddCtx->fw);
4047 pHddCtx->fw = NULL;
4048 }
4049 else
4050 status = VOS_STATUS_E_FAILURE;
4051 }
4052 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4053 if(pHddCtx->nv) {
4054 release_firmware(pHddCtx->nv);
4055 pHddCtx->nv = NULL;
4056 }
4057 else
4058 status = VOS_STATUS_E_FAILURE;
4059
4060 }
4061
4062 EXIT();
4063 return status;
4064}
4065
4066/**---------------------------------------------------------------------------
4067
4068 \brief hdd_request_firmware() -
4069
4070 This function reads the firmware file using the request firmware
4071 API and returns the the firmware data and the firmware file size.
4072
4073 \param - pfileName - Pointer to the file name.
4074 - pCtx - Pointer to the adapter .
4075 - ppfw_data - Pointer to the pointer of the firmware data.
4076 - pSize - Pointer to the file size.
4077
4078 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4079
4080 --------------------------------------------------------------------------*/
4081
4082
4083VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4084{
4085 int status;
4086 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4087 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4088 ENTER();
4089
4090 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4091
4092 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4093
4094 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4095 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4096 __func__, pfileName);
4097 retval = VOS_STATUS_E_FAILURE;
4098 }
4099
4100 else {
4101 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4102 *pSize = pHddCtx->fw->size;
4103 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4104 __func__, *pSize);
4105 }
4106 }
4107 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4108
4109 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4110
4111 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4112 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4113 __func__, pfileName);
4114 retval = VOS_STATUS_E_FAILURE;
4115 }
4116
4117 else {
4118 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4119 *pSize = pHddCtx->nv->size;
4120 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4121 __func__, *pSize);
4122 }
4123 }
4124
4125 EXIT();
4126 return retval;
4127}
4128/**---------------------------------------------------------------------------
4129 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4130
4131 This is the function invoked by SME to inform the result of a full power
4132 request issued by HDD
4133
4134 \param - callbackcontext - Pointer to cookie
4135 status - result of request
4136
4137 \return - None
4138
4139--------------------------------------------------------------------------*/
4140void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4141{
4142 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4143
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004144 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004145 if(&pHddCtx->full_pwr_comp_var)
4146 {
4147 complete(&pHddCtx->full_pwr_comp_var);
4148 }
4149}
4150
4151/**---------------------------------------------------------------------------
4152
4153 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4154
4155 This is the function invoked by SME to inform the result of BMPS
4156 request issued by HDD
4157
4158 \param - callbackcontext - Pointer to cookie
4159 status - result of request
4160
4161 \return - None
4162
4163--------------------------------------------------------------------------*/
4164void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4165{
4166
4167 struct completion *completion_var = (struct completion*) callbackContext;
4168
4169 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4170 if(completion_var != NULL)
4171 {
4172 complete(completion_var);
4173 }
4174}
4175
4176/**---------------------------------------------------------------------------
4177
4178 \brief hdd_get_cfg_file_size() -
4179
4180 This function reads the configuration file using the request firmware
4181 API and returns the configuration file size.
4182
4183 \param - pCtx - Pointer to the adapter .
4184 - pFileName - Pointer to the file name.
4185 - pBufSize - Pointer to the buffer size.
4186
4187 \return - 0 for success, non zero for failure
4188
4189 --------------------------------------------------------------------------*/
4190
4191VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4192{
4193 int status;
4194 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4195
4196 ENTER();
4197
4198 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4199
4200 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4201 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4202 status = VOS_STATUS_E_FAILURE;
4203 }
4204 else {
4205 *pBufSize = pHddCtx->fw->size;
4206 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4207 release_firmware(pHddCtx->fw);
4208 pHddCtx->fw = NULL;
4209 }
4210
4211 EXIT();
4212 return VOS_STATUS_SUCCESS;
4213}
4214
4215/**---------------------------------------------------------------------------
4216
4217 \brief hdd_read_cfg_file() -
4218
4219 This function reads the configuration file using the request firmware
4220 API and returns the cfg data and the buffer size of the configuration file.
4221
4222 \param - pCtx - Pointer to the adapter .
4223 - pFileName - Pointer to the file name.
4224 - pBuffer - Pointer to the data buffer.
4225 - pBufSize - Pointer to the buffer size.
4226
4227 \return - 0 for success, non zero for failure
4228
4229 --------------------------------------------------------------------------*/
4230
4231VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4232 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4233{
4234 int status;
4235 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4236
4237 ENTER();
4238
4239 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4240
4241 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4242 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4243 return VOS_STATUS_E_FAILURE;
4244 }
4245 else {
4246 if(*pBufSize != pHddCtx->fw->size) {
4247 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4248 "file size", __func__);
4249 release_firmware(pHddCtx->fw);
4250 pHddCtx->fw = NULL;
4251 return VOS_STATUS_E_FAILURE;
4252 }
4253 else {
4254 if(pBuffer) {
4255 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4256 }
4257 release_firmware(pHddCtx->fw);
4258 pHddCtx->fw = NULL;
4259 }
4260 }
4261
4262 EXIT();
4263
4264 return VOS_STATUS_SUCCESS;
4265}
4266
4267/**---------------------------------------------------------------------------
4268
Jeff Johnson295189b2012-06-20 16:38:30 -07004269 \brief hdd_set_mac_address() -
4270
4271 This function sets the user specified mac address using
4272 the command ifconfig wlanX hw ether <mac adress>.
4273
4274 \param - dev - Pointer to the net device.
4275 - addr - Pointer to the sockaddr.
4276 \return - 0 for success, non zero for failure
4277
4278 --------------------------------------------------------------------------*/
4279
4280static int hdd_set_mac_address(struct net_device *dev, void *addr)
4281{
4282 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4283 struct sockaddr *psta_mac_addr = addr;
4284 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4285
4286 ENTER();
4287
4288 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4289
4290#ifdef HDD_SESSIONIZE
4291 // set the MAC address though the STA ID CFG.
4292 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4293 (v_U8_t *)&pAdapter->macAddressCurrent,
4294 sizeof( pAdapter->macAddressCurrent ),
4295 hdd_set_mac_addr_cb, VOS_FALSE );
4296#endif
4297
4298 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4299
4300 EXIT();
4301 return halStatus;
4302}
4303
4304tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4305{
4306 int i;
4307 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4308 {
4309 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4310 break;
4311 }
4312
4313 if( VOS_MAX_CONCURRENCY_PERSONA == i)
4314 return NULL;
4315
4316 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
4317 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
4318}
4319
4320void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
4321{
4322 int i;
4323 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4324 {
4325 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
4326 {
4327 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
4328 break;
4329 }
4330 }
4331 return;
4332}
4333
4334#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4335 static struct net_device_ops wlan_drv_ops = {
4336 .ndo_open = hdd_open,
4337 .ndo_stop = hdd_stop,
4338 .ndo_uninit = hdd_uninit,
4339 .ndo_start_xmit = hdd_hard_start_xmit,
4340 .ndo_tx_timeout = hdd_tx_timeout,
4341 .ndo_get_stats = hdd_stats,
4342 .ndo_do_ioctl = hdd_ioctl,
4343 .ndo_set_mac_address = hdd_set_mac_address,
4344 .ndo_select_queue = hdd_select_queue,
4345#ifdef WLAN_FEATURE_PACKET_FILTERING
4346#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
4347 .ndo_set_rx_mode = hdd_set_multicast_list,
4348#else
4349 .ndo_set_multicast_list = hdd_set_multicast_list,
4350#endif //LINUX_VERSION_CODE
4351#endif
4352 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004353 static struct net_device_ops wlan_mon_drv_ops = {
4354 .ndo_open = hdd_mon_open,
4355 .ndo_stop = hdd_stop,
4356 .ndo_uninit = hdd_uninit,
4357 .ndo_start_xmit = hdd_mon_hard_start_xmit,
4358 .ndo_tx_timeout = hdd_tx_timeout,
4359 .ndo_get_stats = hdd_stats,
4360 .ndo_do_ioctl = hdd_ioctl,
4361 .ndo_set_mac_address = hdd_set_mac_address,
4362 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004363
4364#endif
4365
4366void hdd_set_station_ops( struct net_device *pWlanDev )
4367{
4368#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4369 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
4370 pWlanDev->netdev_ops = &wlan_drv_ops;
4371#else
4372 pWlanDev->open = hdd_open;
4373 pWlanDev->stop = hdd_stop;
4374 pWlanDev->uninit = hdd_uninit;
4375 pWlanDev->hard_start_xmit = NULL;
4376 pWlanDev->tx_timeout = hdd_tx_timeout;
4377 pWlanDev->get_stats = hdd_stats;
4378 pWlanDev->do_ioctl = hdd_ioctl;
4379 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
4380 pWlanDev->set_mac_address = hdd_set_mac_address;
4381#endif
4382}
4383
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004384static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07004385{
4386 struct net_device *pWlanDev = NULL;
4387 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004388 /*
4389 * cfg80211 initialization and registration....
4390 */
4391 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
4392
Jeff Johnson295189b2012-06-20 16:38:30 -07004393 if(pWlanDev != NULL)
4394 {
4395
4396 //Save the pointer to the net_device in the HDD adapter
4397 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
4398
Jeff Johnson295189b2012-06-20 16:38:30 -07004399 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
4400
4401 pAdapter->dev = pWlanDev;
4402 pAdapter->pHddCtx = pHddCtx;
4403 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
4404
4405 init_completion(&pAdapter->session_open_comp_var);
4406 init_completion(&pAdapter->session_close_comp_var);
4407 init_completion(&pAdapter->disconnect_comp_var);
4408 init_completion(&pAdapter->linkup_event_var);
4409 init_completion(&pAdapter->cancel_rem_on_chan_var);
4410 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004411#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4412 init_completion(&pAdapter->offchannel_tx_event);
4413#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004414 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004415#ifdef FEATURE_WLAN_TDLS
4416 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07004417 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08004418 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05304419 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004420#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004421 init_completion(&pHddCtx->mc_sus_event_var);
4422 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05304423 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07004424 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07004425 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07004426
Rajeev79dbe4c2013-10-05 11:03:42 +05304427#ifdef FEATURE_WLAN_BATCH_SCAN
4428 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
4429 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
4430 pAdapter->pBatchScanRsp = NULL;
4431 pAdapter->numScanList = 0;
4432 mutex_init(&pAdapter->hdd_batch_scan_lock);
4433#endif
4434
Jeff Johnson295189b2012-06-20 16:38:30 -07004435 pAdapter->isLinkUpSvcNeeded = FALSE;
4436 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
4437 //Init the net_device structure
4438 strlcpy(pWlanDev->name, name, IFNAMSIZ);
4439
4440 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
4441 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
4442 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
4443 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
4444
4445 hdd_set_station_ops( pAdapter->dev );
4446
4447 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004448 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
4449 pAdapter->wdev.wiphy = pHddCtx->wiphy;
4450 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004451 /* set pWlanDev's parent to underlying device */
4452 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
4453 }
4454
4455 return pAdapter;
4456}
4457
4458VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
4459{
4460 struct net_device *pWlanDev = pAdapter->dev;
4461 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4462 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4463 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4464
4465 if( rtnl_lock_held )
4466 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08004467 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07004468 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
4469 {
4470 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
4471 return VOS_STATUS_E_FAILURE;
4472 }
4473 }
4474 if (register_netdevice(pWlanDev))
4475 {
4476 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
4477 return VOS_STATUS_E_FAILURE;
4478 }
4479 }
4480 else
4481 {
4482 if(register_netdev(pWlanDev))
4483 {
4484 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
4485 return VOS_STATUS_E_FAILURE;
4486 }
4487 }
4488 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
4489
4490 return VOS_STATUS_SUCCESS;
4491}
4492
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004493static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07004494{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004495 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07004496
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004497 if (NULL == pAdapter)
4498 {
4499 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
4500 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07004501 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004502
4503 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4504 {
4505 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
4506 return eHAL_STATUS_NOT_INITIALIZED;
4507 }
4508
4509 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
4510
4511 /* need to make sure all of our scheduled work has completed.
4512 * This callback is called from MC thread context, so it is safe to
4513 * to call below flush workqueue API from here.
4514 */
4515 flush_scheduled_work();
4516
4517 /* We can be blocked while waiting for scheduled work to be
4518 * flushed, and the adapter structure can potentially be freed, in
4519 * which case the magic will have been reset. So make sure the
4520 * magic is still good, and hence the adapter structure is still
4521 * valid, before signaling completion */
4522 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
4523 {
4524 complete(&pAdapter->session_close_comp_var);
4525 }
4526
Jeff Johnson295189b2012-06-20 16:38:30 -07004527 return eHAL_STATUS_SUCCESS;
4528}
4529
4530VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
4531{
4532 struct net_device *pWlanDev = pAdapter->dev;
4533 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4534 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4535 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4536 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4537 int rc = 0;
4538
4539 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004540 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07004541 //Open a SME session for future operation
4542 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004543 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004544 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4545 {
4546 hddLog(VOS_TRACE_LEVEL_FATAL,
4547 "sme_OpenSession() failed with status code %08d [x%08lx]",
4548 halStatus, halStatus );
4549 status = VOS_STATUS_E_FAILURE;
4550 goto error_sme_open;
4551 }
4552
4553 //Block on a completion variable. Can't wait forever though.
4554 rc = wait_for_completion_interruptible_timeout(
4555 &pAdapter->session_open_comp_var,
4556 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4557 if (!rc)
4558 {
4559 hddLog(VOS_TRACE_LEVEL_FATAL,
4560 "Session is not opened within timeout period code %08d", rc );
4561 status = VOS_STATUS_E_FAILURE;
4562 goto error_sme_open;
4563 }
4564
4565 // Register wireless extensions
4566 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
4567 {
4568 hddLog(VOS_TRACE_LEVEL_FATAL,
4569 "hdd_register_wext() failed with status code %08d [x%08lx]",
4570 halStatus, halStatus );
4571 status = VOS_STATUS_E_FAILURE;
4572 goto error_register_wext;
4573 }
4574 //Safe to register the hard_start_xmit function again
4575#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4576 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
4577#else
4578 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
4579#endif
4580
4581 //Set the Connection State to Not Connected
4582 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4583
4584 //Set the default operation channel
4585 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
4586
4587 /* Make the default Auth Type as OPEN*/
4588 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4589
4590 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
4591 {
4592 hddLog(VOS_TRACE_LEVEL_FATAL,
4593 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
4594 status, status );
4595 goto error_init_txrx;
4596 }
4597
4598 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4599
4600 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
4601 {
4602 hddLog(VOS_TRACE_LEVEL_FATAL,
4603 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
4604 status, status );
4605 goto error_wmm_init;
4606 }
4607
4608 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4609
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004610#ifdef FEATURE_WLAN_TDLS
4611 if(0 != wlan_hdd_tdls_init(pAdapter))
4612 {
4613 status = VOS_STATUS_E_FAILURE;
4614 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
4615 goto error_tdls_init;
4616 }
4617 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
4618#endif
4619
Jeff Johnson295189b2012-06-20 16:38:30 -07004620 return VOS_STATUS_SUCCESS;
4621
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004622#ifdef FEATURE_WLAN_TDLS
4623error_tdls_init:
4624 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4625 hdd_wmm_adapter_close(pAdapter);
4626#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004627error_wmm_init:
4628 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4629 hdd_deinit_tx_rx(pAdapter);
4630error_init_txrx:
4631 hdd_UnregisterWext(pWlanDev);
4632error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004633 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07004634 {
4635 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004636 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07004637 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004638 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07004639 {
4640 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004641 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004642 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004643 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07004644 }
4645}
4646error_sme_open:
4647 return status;
4648}
4649
Jeff Johnson295189b2012-06-20 16:38:30 -07004650void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4651{
4652 hdd_cfg80211_state_t *cfgState;
4653
4654 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
4655
4656 if( NULL != cfgState->buf )
4657 {
4658 int rc;
4659 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
4660 rc = wait_for_completion_interruptible_timeout(
4661 &pAdapter->tx_action_cnf_event,
4662 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
4663 if(!rc)
4664 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08004665 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004666 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
4667 }
4668 }
4669 return;
4670}
Jeff Johnson295189b2012-06-20 16:38:30 -07004671
4672void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4673{
4674 ENTER();
4675 switch ( pAdapter->device_mode )
4676 {
4677 case WLAN_HDD_INFRA_STATION:
4678 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004679 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004680 {
4681 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
4682 {
4683 hdd_deinit_tx_rx( pAdapter );
4684 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4685 }
4686
4687 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
4688 {
4689 hdd_wmm_adapter_close( pAdapter );
4690 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4691 }
4692
Jeff Johnson295189b2012-06-20 16:38:30 -07004693 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004694#ifdef FEATURE_WLAN_TDLS
4695 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
4696 {
4697 wlan_hdd_tdls_exit(pAdapter);
4698 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
4699 }
4700#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004701
4702 break;
4703 }
4704
4705 case WLAN_HDD_SOFTAP:
4706 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004707 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05304708
4709 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
4710 {
4711 hdd_wmm_adapter_close( pAdapter );
4712 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4713 }
4714
Jeff Johnson295189b2012-06-20 16:38:30 -07004715 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004716
4717 hdd_unregister_hostapd(pAdapter);
4718 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07004719 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07004720 break;
4721 }
4722
4723 case WLAN_HDD_MONITOR:
4724 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004725 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07004726 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
4727 {
4728 hdd_deinit_tx_rx( pAdapter );
4729 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4730 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004731 if(NULL != pAdapterforTx)
4732 {
4733 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
4734 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004735 break;
4736 }
4737
4738
4739 default:
4740 break;
4741 }
4742
4743 EXIT();
4744}
4745
4746void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
4747{
4748 struct net_device *pWlanDev = pAdapter->dev;
4749
Rajeev79dbe4c2013-10-05 11:03:42 +05304750#ifdef FEATURE_WLAN_BATCH_SCAN
4751 tHddBatchScanRsp *pNode;
4752 tHddBatchScanRsp *pPrev;
4753 if (pAdapter)
4754 {
4755 mutex_lock(&pAdapter->hdd_batch_scan_lock);
4756 pNode = pAdapter->pBatchScanRsp;
4757 while (pNode)
4758 {
4759 pPrev = pNode;
4760 pNode = pNode->pNext;
4761 vos_mem_free((v_VOID_t * )pPrev);
4762 }
4763 pAdapter->pBatchScanRsp = NULL;
4764 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
4765 }
4766#endif
4767
Jeff Johnson295189b2012-06-20 16:38:30 -07004768 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
4769 if( rtnl_held )
4770 {
4771 unregister_netdevice(pWlanDev);
4772 }
4773 else
4774 {
4775 unregister_netdev(pWlanDev);
4776 }
4777 // note that the pAdapter is no longer valid at this point
4778 // since the memory has been reclaimed
4779 }
4780
4781}
4782
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004783void hdd_set_pwrparams(hdd_context_t *pHddCtx)
4784{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304785 VOS_STATUS status;
4786 hdd_adapter_t *pAdapter = NULL;
4787 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004788
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304789 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004790
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304791 /*loop through all adapters.*/
4792 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004793 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304794 pAdapter = pAdapterNode->pAdapter;
4795 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
4796 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004797
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304798 { // we skip this registration for modes other than STA and P2P client modes.
4799 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4800 pAdapterNode = pNext;
4801 continue;
4802 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004803
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304804 //Apply Dynamic DTIM For P2P
4805 //Only if ignoreDynamicDtimInP2pMode is not set in ini
4806 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
4807 pHddCtx->cfg_ini->enableModulatedDTIM) &&
4808 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4809 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
4810 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
4811 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
4812 (eConnectionState_Associated ==
4813 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
4814 (pHddCtx->cfg_ini->fIsBmpsEnabled))
4815 {
4816 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004817
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304818 powerRequest.uIgnoreDTIM = 1;
4819 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
4820
4821 if (pHddCtx->cfg_ini->enableModulatedDTIM)
4822 {
4823 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
4824 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
4825 }
4826 else
4827 {
4828 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
4829 }
4830
4831 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
4832 * specified during Enter/Exit BMPS when LCD off*/
4833 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
4834 NULL, eANI_BOOLEAN_FALSE);
4835 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
4836 NULL, eANI_BOOLEAN_FALSE);
4837
4838 /* switch to the DTIM specified in cfg.ini */
4839 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4840 "Switch to DTIM %d", powerRequest.uListenInterval);
4841 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
4842 break;
4843
4844 }
4845
4846 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4847 pAdapterNode = pNext;
4848 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004849}
4850
4851void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
4852{
4853 /*Switch back to DTIM 1*/
4854 tSirSetPowerParamsReq powerRequest = { 0 };
4855
4856 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
4857 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07004858 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004859
4860 /* Update ignoreDTIM and ListedInterval in CFG with default values */
4861 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
4862 NULL, eANI_BOOLEAN_FALSE);
4863 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
4864 NULL, eANI_BOOLEAN_FALSE);
4865
4866 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4867 "Switch to DTIM%d",powerRequest.uListenInterval);
4868 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
4869
4870}
4871
Jeff Johnson295189b2012-06-20 16:38:30 -07004872VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
4873{
4874 VOS_STATUS status = VOS_STATUS_SUCCESS;
4875
4876 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
4877 {
4878 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4879 }
4880
4881 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
4882 {
4883 sme_StartAutoBmpsTimer(pHddCtx->hHal);
4884 }
4885
4886 if (pHddCtx->cfg_ini->fIsImpsEnabled)
4887 {
4888 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4889 }
4890
4891 return status;
4892}
4893
4894VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
4895{
4896 hdd_adapter_t *pAdapter = NULL;
4897 eHalStatus halStatus;
4898 VOS_STATUS status = VOS_STATUS_E_INVAL;
4899 v_BOOL_t disableBmps = FALSE;
4900 v_BOOL_t disableImps = FALSE;
4901
4902 switch(session_type)
4903 {
4904 case WLAN_HDD_INFRA_STATION:
4905 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07004906 case WLAN_HDD_P2P_CLIENT:
4907 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004908 //Exit BMPS -> Is Sta/P2P Client is already connected
4909 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
4910 if((NULL != pAdapter)&&
4911 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4912 {
4913 disableBmps = TRUE;
4914 }
4915
4916 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4917 if((NULL != pAdapter)&&
4918 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4919 {
4920 disableBmps = TRUE;
4921 }
4922
4923 //Exit both Bmps and Imps incase of Go/SAP Mode
4924 if((WLAN_HDD_SOFTAP == session_type) ||
4925 (WLAN_HDD_P2P_GO == session_type))
4926 {
4927 disableBmps = TRUE;
4928 disableImps = TRUE;
4929 }
4930
4931 if(TRUE == disableImps)
4932 {
4933 if (pHddCtx->cfg_ini->fIsImpsEnabled)
4934 {
4935 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4936 }
4937 }
4938
4939 if(TRUE == disableBmps)
4940 {
4941 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
4942 {
4943 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4944
4945 if(eHAL_STATUS_SUCCESS != halStatus)
4946 {
4947 status = VOS_STATUS_E_FAILURE;
4948 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
4949 VOS_ASSERT(0);
4950 return status;
4951 }
4952 }
4953
4954 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
4955 {
4956 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
4957
4958 if(eHAL_STATUS_SUCCESS != halStatus)
4959 {
4960 status = VOS_STATUS_E_FAILURE;
4961 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
4962 VOS_ASSERT(0);
4963 return status;
4964 }
4965 }
4966 }
4967
4968 if((TRUE == disableBmps) ||
4969 (TRUE == disableImps))
4970 {
4971 /* Now, get the chip into Full Power now */
4972 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
4973 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
4974 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
4975
4976 if(halStatus != eHAL_STATUS_SUCCESS)
4977 {
4978 if(halStatus == eHAL_STATUS_PMC_PENDING)
4979 {
4980 //Block on a completion variable. Can't wait forever though
4981 wait_for_completion_interruptible_timeout(
4982 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
4983 }
4984 else
4985 {
4986 status = VOS_STATUS_E_FAILURE;
4987 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
4988 VOS_ASSERT(0);
4989 return status;
4990 }
4991 }
4992
4993 status = VOS_STATUS_SUCCESS;
4994 }
4995
4996 break;
4997 }
4998 return status;
4999}
5000
5001hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005002 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005003 tANI_U8 rtnl_held )
5004{
5005 hdd_adapter_t *pAdapter = NULL;
5006 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5007 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5008 VOS_STATUS exitbmpsStatus;
5009
5010 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5011
5012 //Disable BMPS incase of Concurrency
5013 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5014
5015 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5016 {
5017 //Fail to Exit BMPS
5018 VOS_ASSERT(0);
5019 return NULL;
5020 }
5021
5022 switch(session_type)
5023 {
5024 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005025 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005026 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005027 {
5028 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5029
5030 if( NULL == pAdapter )
5031 return NULL;
5032
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305033#ifdef FEATURE_WLAN_TDLS
5034 /* A Mutex Lock is introduced while changing/initializing the mode to
5035 * protect the concurrent access for the Adapters by TDLS module.
5036 */
5037 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5038 {
5039 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5040 "%s: unable to lock list", __func__);
5041 return NULL;
5042 }
5043#endif
5044
Jeff Johnsone7245742012-09-05 17:12:55 -07005045 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5046 NL80211_IFTYPE_P2P_CLIENT:
5047 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005048
Jeff Johnson295189b2012-06-20 16:38:30 -07005049 pAdapter->device_mode = session_type;
5050
5051 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305052#ifdef FEATURE_WLAN_TDLS
5053 mutex_unlock(&pHddCtx->tdls_lock);
5054#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005055 if( VOS_STATUS_SUCCESS != status )
5056 goto err_free_netdev;
5057
5058 status = hdd_register_interface( pAdapter, rtnl_held );
5059 if( VOS_STATUS_SUCCESS != status )
5060 {
5061 hdd_deinit_adapter(pHddCtx, pAdapter);
5062 goto err_free_netdev;
5063 }
5064 //Stop the Interface TX queue.
5065 netif_tx_disable(pAdapter->dev);
5066 //netif_tx_disable(pWlanDev);
5067 netif_carrier_off(pAdapter->dev);
5068
5069 break;
5070 }
5071
Jeff Johnson295189b2012-06-20 16:38:30 -07005072 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005073 case WLAN_HDD_SOFTAP:
5074 {
5075 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5076 if( NULL == pAdapter )
5077 return NULL;
5078
Jeff Johnson295189b2012-06-20 16:38:30 -07005079 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5080 NL80211_IFTYPE_AP:
5081 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005082 pAdapter->device_mode = session_type;
5083
5084 status = hdd_init_ap_mode(pAdapter);
5085 if( VOS_STATUS_SUCCESS != status )
5086 goto err_free_netdev;
5087
5088 status = hdd_register_hostapd( pAdapter, rtnl_held );
5089 if( VOS_STATUS_SUCCESS != status )
5090 {
5091 hdd_deinit_adapter(pHddCtx, pAdapter);
5092 goto err_free_netdev;
5093 }
5094
5095 netif_tx_disable(pAdapter->dev);
5096 netif_carrier_off(pAdapter->dev);
5097
5098 hdd_set_conparam( 1 );
5099 break;
5100 }
5101 case WLAN_HDD_MONITOR:
5102 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005103 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5104 if( NULL == pAdapter )
5105 return NULL;
5106
5107 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5108 pAdapter->device_mode = session_type;
5109 status = hdd_register_interface( pAdapter, rtnl_held );
5110#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5111 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5112#else
5113 pAdapter->dev->open = hdd_mon_open;
5114 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5115#endif
5116 hdd_init_tx_rx( pAdapter );
5117 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5118 //Set adapter to be used for data tx. It will use either GO or softap.
5119 pAdapter->sessionCtx.monitor.pAdapterForTx =
5120 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005121 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5122 {
5123 pAdapter->sessionCtx.monitor.pAdapterForTx =
5124 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5125 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005126 /* This workqueue will be used to transmit management packet over
5127 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005128 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5129 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5130 return NULL;
5131 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005132
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5134 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005135 }
5136 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005137 case WLAN_HDD_FTM:
5138 {
5139 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5140
5141 if( NULL == pAdapter )
5142 return NULL;
5143 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5144 * message while loading driver in FTM mode. */
5145 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5146 pAdapter->device_mode = session_type;
5147 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305148
5149 hdd_init_tx_rx( pAdapter );
5150
5151 //Stop the Interface TX queue.
5152 netif_tx_disable(pAdapter->dev);
5153 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005154 }
5155 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005156 default:
5157 {
5158 VOS_ASSERT(0);
5159 return NULL;
5160 }
5161 }
5162
5163
5164 if( VOS_STATUS_SUCCESS == status )
5165 {
5166 //Add it to the hdd's session list.
5167 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5168 if( NULL == pHddAdapterNode )
5169 {
5170 status = VOS_STATUS_E_NOMEM;
5171 }
5172 else
5173 {
5174 pHddAdapterNode->pAdapter = pAdapter;
5175 status = hdd_add_adapter_back ( pHddCtx,
5176 pHddAdapterNode );
5177 }
5178 }
5179
5180 if( VOS_STATUS_SUCCESS != status )
5181 {
5182 if( NULL != pAdapter )
5183 {
5184 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5185 pAdapter = NULL;
5186 }
5187 if( NULL != pHddAdapterNode )
5188 {
5189 vos_mem_free( pHddAdapterNode );
5190 }
5191
5192 goto resume_bmps;
5193 }
5194
5195 if(VOS_STATUS_SUCCESS == status)
5196 {
5197 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5198
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005199 //Initialize the WoWL service
5200 if(!hdd_init_wowl(pAdapter))
5201 {
5202 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5203 goto err_free_netdev;
5204 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005205 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005206 return pAdapter;
5207
5208err_free_netdev:
5209 free_netdev(pAdapter->dev);
5210 wlan_hdd_release_intf_addr( pHddCtx,
5211 pAdapter->macAddressCurrent.bytes );
5212
5213resume_bmps:
5214 //If bmps disabled enable it
5215 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5216 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305217 if (pHddCtx->hdd_wlan_suspended)
5218 {
5219 hdd_set_pwrparams(pHddCtx);
5220 }
5221 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005222 }
5223 return NULL;
5224}
5225
5226VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5227 tANI_U8 rtnl_held )
5228{
5229 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5230 VOS_STATUS status;
5231
5232 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5233 if( VOS_STATUS_SUCCESS != status )
5234 return status;
5235
5236 while ( pCurrent->pAdapter != pAdapter )
5237 {
5238 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5239 if( VOS_STATUS_SUCCESS != status )
5240 break;
5241
5242 pCurrent = pNext;
5243 }
5244 pAdapterNode = pCurrent;
5245 if( VOS_STATUS_SUCCESS == status )
5246 {
5247 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5248 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305249
5250#ifdef FEATURE_WLAN_TDLS
5251
5252 /* A Mutex Lock is introduced while changing/initializing the mode to
5253 * protect the concurrent access for the Adapters by TDLS module.
5254 */
5255 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5256 {
5257 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5258 "%s: unable to lock list", __func__);
5259 return VOS_STATUS_E_FAILURE;
5260 }
5261#endif
5262
Jeff Johnson295189b2012-06-20 16:38:30 -07005263 hdd_remove_adapter( pHddCtx, pAdapterNode );
5264 vos_mem_free( pAdapterNode );
5265
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305266#ifdef FEATURE_WLAN_TDLS
5267 mutex_unlock(&pHddCtx->tdls_lock);
5268#endif
5269
Jeff Johnson295189b2012-06-20 16:38:30 -07005270
5271 /* If there is a single session of STA/P2P client, re-enable BMPS */
5272 if ((!vos_concurrent_sessions_running()) &&
5273 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5274 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5275 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305276 if (pHddCtx->hdd_wlan_suspended)
5277 {
5278 hdd_set_pwrparams(pHddCtx);
5279 }
5280 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005281 }
5282
5283 return VOS_STATUS_SUCCESS;
5284 }
5285
5286 return VOS_STATUS_E_FAILURE;
5287}
5288
5289VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5290{
5291 hdd_adapter_list_node_t *pHddAdapterNode;
5292 VOS_STATUS status;
5293
5294 ENTER();
5295
5296 do
5297 {
5298 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5299 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5300 {
5301 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
5302 vos_mem_free( pHddAdapterNode );
5303 }
5304 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
5305
5306 EXIT();
5307
5308 return VOS_STATUS_SUCCESS;
5309}
5310
5311void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
5312{
5313 v_U8_t addIE[1] = {0};
5314
5315 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5316 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
5317 eANI_BOOLEAN_FALSE) )
5318 {
5319 hddLog(LOGE,
5320 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
5321 }
5322
5323 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5324 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
5325 eANI_BOOLEAN_FALSE) )
5326 {
5327 hddLog(LOGE,
5328 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
5329 }
5330
5331 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5332 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
5333 eANI_BOOLEAN_FALSE) )
5334 {
5335 hddLog(LOGE,
5336 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
5337 }
5338}
5339
5340VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5341{
5342 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5343 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5344 union iwreq_data wrqu;
5345
5346 ENTER();
5347
5348 switch(pAdapter->device_mode)
5349 {
5350 case WLAN_HDD_INFRA_STATION:
5351 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005352 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005353 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5354 {
5355 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
5356 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5357 pAdapter->sessionId,
5358 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5359 else
5360 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5361 pAdapter->sessionId,
5362 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5363 //success implies disconnect command got queued up successfully
5364 if(halStatus == eHAL_STATUS_SUCCESS)
5365 {
5366 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
5367 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5368 }
5369 memset(&wrqu, '\0', sizeof(wrqu));
5370 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5371 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5372 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
5373 }
5374 else
5375 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305376 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005377 }
5378
5379 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
5380 {
5381 INIT_COMPLETION(pAdapter->session_close_comp_var);
5382 if (eHAL_STATUS_SUCCESS ==
5383 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
5384 hdd_smeCloseSessionCallback, pAdapter))
5385 {
5386 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005387 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005388 &pAdapter->session_close_comp_var,
5389 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5390 }
5391 }
5392
5393 break;
5394
5395 case WLAN_HDD_SOFTAP:
5396 case WLAN_HDD_P2P_GO:
5397 //Any softap specific cleanup here...
5398 mutex_lock(&pHddCtx->sap_lock);
5399 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5400 {
5401 VOS_STATUS status;
5402 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5403
5404 //Stop Bss.
5405 status = WLANSAP_StopBss(pHddCtx->pvosContext);
5406 if (VOS_IS_STATUS_SUCCESS(status))
5407 {
5408 hdd_hostapd_state_t *pHostapdState =
5409 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5410
5411 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
5412
5413 if (!VOS_IS_STATUS_SUCCESS(status))
5414 {
5415 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005416 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005417 }
5418 }
5419 else
5420 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005421 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005422 }
5423 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
5424
5425 if (eHAL_STATUS_FAILURE ==
5426 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5427 0, NULL, eANI_BOOLEAN_FALSE))
5428 {
5429 hddLog(LOGE,
5430 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005431 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005432 }
5433
5434 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
5435 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5436 eANI_BOOLEAN_FALSE) )
5437 {
5438 hddLog(LOGE,
5439 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
5440 }
5441
5442 // Reset WNI_CFG_PROBE_RSP Flags
5443 wlan_hdd_reset_prob_rspies(pAdapter);
5444 kfree(pAdapter->sessionCtx.ap.beacon);
5445 pAdapter->sessionCtx.ap.beacon = NULL;
5446 }
5447 mutex_unlock(&pHddCtx->sap_lock);
5448 break;
5449 case WLAN_HDD_MONITOR:
5450 break;
5451 default:
5452 break;
5453 }
5454
5455 EXIT();
5456 return VOS_STATUS_SUCCESS;
5457}
5458
5459VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
5460{
5461 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5462 VOS_STATUS status;
5463 hdd_adapter_t *pAdapter;
5464
5465 ENTER();
5466
5467 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5468
5469 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5470 {
5471 pAdapter = pAdapterNode->pAdapter;
5472 netif_tx_disable(pAdapter->dev);
5473 netif_carrier_off(pAdapter->dev);
5474
5475 hdd_stop_adapter( pHddCtx, pAdapter );
5476
5477 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5478 pAdapterNode = pNext;
5479 }
5480
5481 EXIT();
5482
5483 return VOS_STATUS_SUCCESS;
5484}
5485
5486VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
5487{
5488 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5489 VOS_STATUS status;
5490 hdd_adapter_t *pAdapter;
5491
5492 ENTER();
5493
5494 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5495
5496 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5497 {
5498 pAdapter = pAdapterNode->pAdapter;
5499 netif_tx_disable(pAdapter->dev);
5500 netif_carrier_off(pAdapter->dev);
5501
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005502 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
5503
Jeff Johnson295189b2012-06-20 16:38:30 -07005504 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305505 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5506 {
5507 hdd_wmm_adapter_close( pAdapter );
5508 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5509 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005510
5511 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5512 pAdapterNode = pNext;
5513 }
5514
5515 EXIT();
5516
5517 return VOS_STATUS_SUCCESS;
5518}
5519
5520VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
5521{
5522 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5523 VOS_STATUS status;
5524 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305525 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07005526
5527 ENTER();
5528
5529 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5530
5531 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5532 {
5533 pAdapter = pAdapterNode->pAdapter;
5534
5535 switch(pAdapter->device_mode)
5536 {
5537 case WLAN_HDD_INFRA_STATION:
5538 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005539 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305540
5541 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
5542
Jeff Johnson295189b2012-06-20 16:38:30 -07005543 hdd_init_station_mode(pAdapter);
5544 /* Open the gates for HDD to receive Wext commands */
5545 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005546 pHddCtx->scan_info.mScanPending = FALSE;
5547 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005548
5549 //Trigger the initial scan
5550 hdd_wlan_initial_scan(pAdapter);
5551
5552 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305553 if (eConnectionState_Associated == connState ||
5554 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07005555 {
5556 union iwreq_data wrqu;
5557 memset(&wrqu, '\0', sizeof(wrqu));
5558 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5559 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5560 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005561 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005562
Jeff Johnson295189b2012-06-20 16:38:30 -07005563 /* indicate disconnected event to nl80211 */
5564 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
5565 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005566 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305567 else if (eConnectionState_Connecting == connState)
5568 {
5569 /*
5570 * Indicate connect failure to supplicant if we were in the
5571 * process of connecting
5572 */
5573 cfg80211_connect_result(pAdapter->dev, NULL,
5574 NULL, 0, NULL, 0,
5575 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
5576 GFP_KERNEL);
5577 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005578 break;
5579
5580 case WLAN_HDD_SOFTAP:
5581 /* softAP can handle SSR */
5582 break;
5583
5584 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07005585 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07005586 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07005587 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005588 break;
5589
5590 case WLAN_HDD_MONITOR:
5591 /* monitor interface start */
5592 break;
5593 default:
5594 break;
5595 }
5596
5597 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5598 pAdapterNode = pNext;
5599 }
5600
5601 EXIT();
5602
5603 return VOS_STATUS_SUCCESS;
5604}
5605
5606VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
5607{
5608 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5609 hdd_adapter_t *pAdapter;
5610 VOS_STATUS status;
5611 v_U32_t roamId;
5612
5613 ENTER();
5614
5615 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5616
5617 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5618 {
5619 pAdapter = pAdapterNode->pAdapter;
5620
5621 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5622 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5623 {
5624 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5625 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5626
5627 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5628 init_completion(&pAdapter->disconnect_comp_var);
5629 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
5630 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5631
5632 wait_for_completion_interruptible_timeout(
5633 &pAdapter->disconnect_comp_var,
5634 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5635
5636 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
5637 pHddCtx->isAmpAllowed = VOS_FALSE;
5638 sme_RoamConnect(pHddCtx->hHal,
5639 pAdapter->sessionId, &(pWextState->roamProfile),
5640 &roamId);
5641 }
5642
5643 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5644 pAdapterNode = pNext;
5645 }
5646
5647 EXIT();
5648
5649 return VOS_STATUS_SUCCESS;
5650}
5651
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07005652void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
5653{
5654 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5655 VOS_STATUS status;
5656 hdd_adapter_t *pAdapter;
5657 hdd_station_ctx_t *pHddStaCtx;
5658 hdd_ap_ctx_t *pHddApCtx;
5659 hdd_hostapd_state_t * pHostapdState;
5660 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
5661 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
5662 const char *p2pMode = "DEV";
5663 const char *ccMode = "Standalone";
5664 int n;
5665
5666 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5667 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5668 {
5669 pAdapter = pAdapterNode->pAdapter;
5670 switch (pAdapter->device_mode) {
5671 case WLAN_HDD_INFRA_STATION:
5672 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5673 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
5674 staChannel = pHddStaCtx->conn_info.operationChannel;
5675 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
5676 }
5677 break;
5678 case WLAN_HDD_P2P_CLIENT:
5679 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5680 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
5681 p2pChannel = pHddStaCtx->conn_info.operationChannel;
5682 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
5683 p2pMode = "CLI";
5684 }
5685 break;
5686 case WLAN_HDD_P2P_GO:
5687 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
5688 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5689 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
5690 p2pChannel = pHddApCtx->operatingChannel;
5691 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
5692 }
5693 p2pMode = "GO";
5694 break;
5695 case WLAN_HDD_SOFTAP:
5696 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
5697 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5698 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
5699 apChannel = pHddApCtx->operatingChannel;
5700 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
5701 }
5702 break;
5703 default:
5704 break;
5705 }
5706 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5707 pAdapterNode = pNext;
5708 }
5709 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
5710 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
5711 }
5712 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
5713 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
5714 if (p2pChannel > 0) {
5715 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
5716 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
5717 }
5718 if (apChannel > 0) {
5719 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
5720 apChannel, MAC_ADDR_ARRAY(apBssid));
5721 }
5722
5723 if (p2pChannel > 0 && apChannel > 0) {
5724 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
5725 }
5726}
5727
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005728bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005729{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005730 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07005731}
5732
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005733/* Once SSR is disabled then it cannot be set. */
5734void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07005735{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005736 if (HDD_SSR_DISABLED == isSsrRequired)
5737 return;
5738
Jeff Johnson295189b2012-06-20 16:38:30 -07005739 isSsrRequired = value;
5740}
5741
5742VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
5743 hdd_adapter_list_node_t** ppAdapterNode)
5744{
5745 VOS_STATUS status;
5746 spin_lock(&pHddCtx->hddAdapters.lock);
5747 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
5748 (hdd_list_node_t**) ppAdapterNode );
5749 spin_unlock(&pHddCtx->hddAdapters.lock);
5750 return status;
5751}
5752
5753VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
5754 hdd_adapter_list_node_t* pAdapterNode,
5755 hdd_adapter_list_node_t** pNextAdapterNode)
5756{
5757 VOS_STATUS status;
5758 spin_lock(&pHddCtx->hddAdapters.lock);
5759 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
5760 (hdd_list_node_t*) pAdapterNode,
5761 (hdd_list_node_t**)pNextAdapterNode );
5762
5763 spin_unlock(&pHddCtx->hddAdapters.lock);
5764 return status;
5765}
5766
5767VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
5768 hdd_adapter_list_node_t* pAdapterNode)
5769{
5770 VOS_STATUS status;
5771 spin_lock(&pHddCtx->hddAdapters.lock);
5772 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
5773 &pAdapterNode->node );
5774 spin_unlock(&pHddCtx->hddAdapters.lock);
5775 return status;
5776}
5777
5778VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
5779 hdd_adapter_list_node_t** ppAdapterNode)
5780{
5781 VOS_STATUS status;
5782 spin_lock(&pHddCtx->hddAdapters.lock);
5783 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
5784 (hdd_list_node_t**) ppAdapterNode );
5785 spin_unlock(&pHddCtx->hddAdapters.lock);
5786 return status;
5787}
5788
5789VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
5790 hdd_adapter_list_node_t* pAdapterNode)
5791{
5792 VOS_STATUS status;
5793 spin_lock(&pHddCtx->hddAdapters.lock);
5794 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
5795 (hdd_list_node_t*) pAdapterNode );
5796 spin_unlock(&pHddCtx->hddAdapters.lock);
5797 return status;
5798}
5799
5800VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
5801 hdd_adapter_list_node_t* pAdapterNode)
5802{
5803 VOS_STATUS status;
5804 spin_lock(&pHddCtx->hddAdapters.lock);
5805 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
5806 (hdd_list_node_t*) pAdapterNode );
5807 spin_unlock(&pHddCtx->hddAdapters.lock);
5808 return status;
5809}
5810
5811hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
5812 tSirMacAddr macAddr )
5813{
5814 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5815 hdd_adapter_t *pAdapter;
5816 VOS_STATUS status;
5817
5818 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5819
5820 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5821 {
5822 pAdapter = pAdapterNode->pAdapter;
5823
5824 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
5825 macAddr, sizeof(tSirMacAddr) ) )
5826 {
5827 return pAdapter;
5828 }
5829 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5830 pAdapterNode = pNext;
5831 }
5832
5833 return NULL;
5834
5835}
5836
5837hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
5838{
5839 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5840 hdd_adapter_t *pAdapter;
5841 VOS_STATUS status;
5842
5843 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5844
5845 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5846 {
5847 pAdapter = pAdapterNode->pAdapter;
5848
5849 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
5850 IFNAMSIZ ) )
5851 {
5852 return pAdapter;
5853 }
5854 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5855 pAdapterNode = pNext;
5856 }
5857
5858 return NULL;
5859
5860}
5861
5862hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
5863{
5864 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5865 hdd_adapter_t *pAdapter;
5866 VOS_STATUS status;
5867
5868 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5869
5870 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5871 {
5872 pAdapter = pAdapterNode->pAdapter;
5873
5874 if( pAdapter && (mode == pAdapter->device_mode) )
5875 {
5876 return pAdapter;
5877 }
5878 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5879 pAdapterNode = pNext;
5880 }
5881
5882 return NULL;
5883
5884}
5885
5886//Remove this function later
5887hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
5888{
5889 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5890 hdd_adapter_t *pAdapter;
5891 VOS_STATUS status;
5892
5893 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5894
5895 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5896 {
5897 pAdapter = pAdapterNode->pAdapter;
5898
5899 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
5900 {
5901 return pAdapter;
5902 }
5903
5904 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5905 pAdapterNode = pNext;
5906 }
5907
5908 return NULL;
5909
5910}
5911
Jeff Johnson295189b2012-06-20 16:38:30 -07005912/**---------------------------------------------------------------------------
5913
5914 \brief hdd_set_monitor_tx_adapter() -
5915
5916 This API initializes the adapter to be used while transmitting on monitor
5917 adapter.
5918
5919 \param - pHddCtx - Pointer to the HDD context.
5920 pAdapter - Adapter that will used for TX. This can be NULL.
5921 \return - None.
5922 --------------------------------------------------------------------------*/
5923void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5924{
5925 hdd_adapter_t *pMonAdapter;
5926
5927 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
5928
5929 if( NULL != pMonAdapter )
5930 {
5931 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
5932 }
5933}
Jeff Johnson295189b2012-06-20 16:38:30 -07005934/**---------------------------------------------------------------------------
5935
5936 \brief hdd_select_queue() -
5937
5938 This API returns the operating channel of the requested device mode
5939
5940 \param - pHddCtx - Pointer to the HDD context.
5941 - mode - Device mode for which operating channel is required
5942 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
5943 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
5944 \return - channel number. "0" id the requested device is not found OR it is not connected.
5945 --------------------------------------------------------------------------*/
5946v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
5947{
5948 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5949 VOS_STATUS status;
5950 hdd_adapter_t *pAdapter;
5951 v_U8_t operatingChannel = 0;
5952
5953 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5954
5955 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5956 {
5957 pAdapter = pAdapterNode->pAdapter;
5958
5959 if( mode == pAdapter->device_mode )
5960 {
5961 switch(pAdapter->device_mode)
5962 {
5963 case WLAN_HDD_INFRA_STATION:
5964 case WLAN_HDD_P2P_CLIENT:
5965 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5966 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
5967 break;
5968 case WLAN_HDD_SOFTAP:
5969 case WLAN_HDD_P2P_GO:
5970 /*softap connection info */
5971 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5972 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
5973 break;
5974 default:
5975 break;
5976 }
5977
5978 break; //Found the device of interest. break the loop
5979 }
5980
5981 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5982 pAdapterNode = pNext;
5983 }
5984 return operatingChannel;
5985}
5986
5987#ifdef WLAN_FEATURE_PACKET_FILTERING
5988/**---------------------------------------------------------------------------
5989
5990 \brief hdd_set_multicast_list() -
5991
5992 This used to set the multicast address list.
5993
5994 \param - dev - Pointer to the WLAN device.
5995 - skb - Pointer to OS packet (sk_buff).
5996 \return - success/fail
5997
5998 --------------------------------------------------------------------------*/
5999static void hdd_set_multicast_list(struct net_device *dev)
6000{
6001 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006002 int mc_count;
6003 int i = 0;
6004 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306005
6006 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006007 {
6008 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306009 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006010 return;
6011 }
6012
6013 if (dev->flags & IFF_ALLMULTI)
6014 {
6015 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006016 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306017 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006018 }
6019 else
6020 {
6021 mc_count = netdev_mc_count(dev);
6022 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006023 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006024 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6025 {
6026 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006027 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306028 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 return;
6030 }
6031
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306032 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006033
6034 netdev_for_each_mc_addr(ha, dev) {
6035 if (i == mc_count)
6036 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306037 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6038 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6039 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006040 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306041 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006042 i++;
6043 }
6044 }
6045 return;
6046}
6047#endif
6048
6049/**---------------------------------------------------------------------------
6050
6051 \brief hdd_select_queue() -
6052
6053 This function is registered with the Linux OS for network
6054 core to decide which queue to use first.
6055
6056 \param - dev - Pointer to the WLAN device.
6057 - skb - Pointer to OS packet (sk_buff).
6058 \return - ac, Queue Index/access category corresponding to UP in IP header
6059
6060 --------------------------------------------------------------------------*/
6061v_U16_t hdd_select_queue(struct net_device *dev,
6062 struct sk_buff *skb)
6063{
6064 return hdd_wmm_select_queue(dev, skb);
6065}
6066
6067
6068/**---------------------------------------------------------------------------
6069
6070 \brief hdd_wlan_initial_scan() -
6071
6072 This function triggers the initial scan
6073
6074 \param - pAdapter - Pointer to the HDD adapter.
6075
6076 --------------------------------------------------------------------------*/
6077void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6078{
6079 tCsrScanRequest scanReq;
6080 tCsrChannelInfo channelInfo;
6081 eHalStatus halStatus;
6082 unsigned long scanId;
6083 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6084
6085 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6086 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6087 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6088
6089 if(sme_Is11dSupported(pHddCtx->hHal))
6090 {
6091 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6092 if ( HAL_STATUS_SUCCESS( halStatus ) )
6093 {
6094 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6095 if( !scanReq.ChannelInfo.ChannelList )
6096 {
6097 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6098 vos_mem_free(channelInfo.ChannelList);
6099 return;
6100 }
6101 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6102 channelInfo.numOfChannels);
6103 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6104 vos_mem_free(channelInfo.ChannelList);
6105 }
6106
6107 scanReq.scanType = eSIR_PASSIVE_SCAN;
6108 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6109 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6110 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6111 }
6112 else
6113 {
6114 scanReq.scanType = eSIR_ACTIVE_SCAN;
6115 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6116 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6117 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6118 }
6119
6120 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6121 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6122 {
6123 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6124 __func__, halStatus );
6125 }
6126
6127 if(sme_Is11dSupported(pHddCtx->hHal))
6128 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6129}
6130
6131struct fullPowerContext
6132{
6133 struct completion completion;
6134 unsigned int magic;
6135};
6136#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6137
6138/**---------------------------------------------------------------------------
6139
6140 \brief hdd_full_power_callback() - HDD full power callback function
6141
6142 This is the function invoked by SME to inform the result of a full power
6143 request issued by HDD
6144
6145 \param - callbackcontext - Pointer to cookie
6146 \param - status - result of request
6147
6148 \return - None
6149
6150 --------------------------------------------------------------------------*/
6151static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6152{
6153 struct fullPowerContext *pContext = callbackContext;
6154
6155 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306156 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006157
6158 if (NULL == callbackContext)
6159 {
6160 hddLog(VOS_TRACE_LEVEL_ERROR,
6161 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006162 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006163 return;
6164 }
6165
6166 /* there is a race condition that exists between this callback function
6167 and the caller since the caller could time out either before or
6168 while this code is executing. we'll assume the timeout hasn't
6169 occurred, but we'll verify that right before we save our work */
6170
6171 if (POWER_CONTEXT_MAGIC != pContext->magic)
6172 {
6173 /* the caller presumably timed out so there is nothing we can do */
6174 hddLog(VOS_TRACE_LEVEL_WARN,
6175 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006176 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006177 return;
6178 }
6179
6180 /* the race is on. caller could have timed out immediately after
6181 we verified the magic, but if so, caller will wait a short time
6182 for us to notify the caller, so the context will stay valid */
6183 complete(&pContext->completion);
6184}
6185
6186/**---------------------------------------------------------------------------
6187
6188 \brief hdd_wlan_exit() - HDD WLAN exit function
6189
6190 This is the driver exit point (invoked during rmmod)
6191
6192 \param - pHddCtx - Pointer to the HDD Context
6193
6194 \return - None
6195
6196 --------------------------------------------------------------------------*/
6197void hdd_wlan_exit(hdd_context_t *pHddCtx)
6198{
6199 eHalStatus halStatus;
6200 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6201 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306202 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006203 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006204 struct fullPowerContext powerContext;
6205 long lrc;
6206
6207 ENTER();
6208
Jeff Johnson88ba7742013-02-27 14:36:02 -08006209 if (VOS_FTM_MODE != hdd_get_conparam())
6210 {
6211 // Unloading, restart logic is no more required.
6212 wlan_hdd_restart_deinit(pHddCtx);
6213 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006214
Jeff Johnson295189b2012-06-20 16:38:30 -07006215 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006216 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006217 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006218 {
6219 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6220 WLAN_HDD_INFRA_STATION);
6221 if (pAdapter == NULL)
6222 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6223
6224 if (pAdapter != NULL)
6225 {
6226 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6227 hdd_UnregisterWext(pAdapter->dev);
6228 }
6229 }
6230 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006231
Jeff Johnson295189b2012-06-20 16:38:30 -07006232 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006233 {
6234 wlan_hdd_ftm_close(pHddCtx);
6235 goto free_hdd_ctx;
6236 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006237 //Stop the Interface TX queue.
6238 //netif_tx_disable(pWlanDev);
6239 //netif_carrier_off(pWlanDev);
6240
Jeff Johnson295189b2012-06-20 16:38:30 -07006241 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6242 {
6243 pAdapter = hdd_get_adapter(pHddCtx,
6244 WLAN_HDD_SOFTAP);
6245 }
6246 else
6247 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006248 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006249 {
6250 pAdapter = hdd_get_adapter(pHddCtx,
6251 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006252 if (pAdapter == NULL)
6253 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006254 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006255 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006256 /* DeRegister with platform driver as client for Suspend/Resume */
6257 vosStatus = hddDeregisterPmOps(pHddCtx);
6258 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6259 {
6260 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6261 VOS_ASSERT(0);
6262 }
6263
6264 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6265 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6266 {
6267 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6268 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006269
6270 // Cancel any outstanding scan requests. We are about to close all
6271 // of our adapters, but an adapter structure is what SME passes back
6272 // to our callback function. Hence if there are any outstanding scan
6273 // requests then there is a race condition between when the adapter
6274 // is closed and when the callback is invoked. We try to resolve that
6275 // race condition here by canceling any outstanding scans before we
6276 // close the adapters.
6277 // Note that the scans may be cancelled in an asynchronous manner, so
6278 // ideally there needs to be some kind of synchronization. Rather than
6279 // introduce a new synchronization here, we will utilize the fact that
6280 // we are about to Request Full Power, and since that is synchronized,
6281 // the expectation is that by the time Request Full Power has completed,
6282 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006283 if (NULL != pAdapter)
6284 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6285 else
6286 hddLog(VOS_TRACE_LEVEL_ERROR,
6287 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006288
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006289 //Stop the traffic monitor timer
6290 if ( VOS_TIMER_STATE_RUNNING ==
6291 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6292 {
6293 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6294 }
6295
6296 // Destroy the traffic monitor timer
6297 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
6298 &pHddCtx->tx_rx_trafficTmr)))
6299 {
6300 hddLog(VOS_TRACE_LEVEL_ERROR,
6301 "%s: Cannot deallocate Traffic monitor timer", __func__);
6302 }
6303
Jeff Johnson295189b2012-06-20 16:38:30 -07006304 //Disable IMPS/BMPS as we do not want the device to enter any power
6305 //save mode during shutdown
6306 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6307 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6308 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
6309
6310 //Ensure that device is in full power as we will touch H/W during vos_Stop
6311 init_completion(&powerContext.completion);
6312 powerContext.magic = POWER_CONTEXT_MAGIC;
6313
6314 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
6315 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
6316
6317 if (eHAL_STATUS_SUCCESS != halStatus)
6318 {
6319 if (eHAL_STATUS_PMC_PENDING == halStatus)
6320 {
6321 /* request was sent -- wait for the response */
6322 lrc = wait_for_completion_interruptible_timeout(
6323 &powerContext.completion,
6324 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
6325 /* either we have a response or we timed out
6326 either way, first invalidate our magic */
6327 powerContext.magic = 0;
6328 if (lrc <= 0)
6329 {
6330 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006331 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07006332 /* there is a race condition such that the callback
6333 function could be executing at the same time we are. of
6334 primary concern is if the callback function had already
6335 verified the "magic" but hasn't yet set the completion
6336 variable. Since the completion variable is on our
6337 stack, we'll delay just a bit to make sure the data is
6338 still valid if that is the case */
6339 msleep(50);
6340 }
6341 }
6342 else
6343 {
6344 hddLog(VOS_TRACE_LEVEL_ERROR,
6345 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006346 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07006347 VOS_ASSERT(0);
6348 /* continue -- need to clean up as much as possible */
6349 }
6350 }
6351
Yue Ma0d4891e2013-08-06 17:01:45 -07006352 hdd_debugfs_exit(pHddCtx);
6353
Jeff Johnson295189b2012-06-20 16:38:30 -07006354 // Unregister the Net Device Notifier
6355 unregister_netdevice_notifier(&hdd_netdev_notifier);
6356
Jeff Johnson295189b2012-06-20 16:38:30 -07006357 hdd_stop_all_adapters( pHddCtx );
6358
Jeff Johnson295189b2012-06-20 16:38:30 -07006359#ifdef WLAN_BTAMP_FEATURE
6360 vosStatus = WLANBAP_Stop(pVosContext);
6361 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6362 {
6363 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
6364 "%s: Failed to stop BAP",__func__);
6365 }
6366#endif //WLAN_BTAMP_FEATURE
6367
6368 //Stop all the modules
6369 vosStatus = vos_stop( pVosContext );
6370 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6371 {
6372 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6373 "%s: Failed to stop VOSS",__func__);
6374 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6375 }
6376
Jeff Johnson295189b2012-06-20 16:38:30 -07006377 //Assert Deep sleep signal now to put Libra HW in lowest power state
6378 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6379 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6380
6381 //Vote off any PMIC voltage supplies
6382 vos_chipPowerDown(NULL, NULL, NULL);
6383
6384 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
6385
Leo Chang59cdc7e2013-07-10 10:08:21 -07006386
Jeff Johnson295189b2012-06-20 16:38:30 -07006387 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07006388 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006389
6390 //Close the scheduler before calling vos_close to make sure no thread is
6391 // scheduled after the each module close is called i.e after all the data
6392 // structures are freed.
6393 vosStatus = vos_sched_close( pVosContext );
6394 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
6395 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6396 "%s: Failed to close VOSS Scheduler",__func__);
6397 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6398 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006399#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006400#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6401 /* Destroy the wake lock */
6402 wake_lock_destroy(&pHddCtx->rx_wake_lock);
6403#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006404 /* Destroy the wake lock */
6405 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006406#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006407
6408 //Close VOSS
6409 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
6410 vos_close(pVosContext);
6411
Jeff Johnson295189b2012-06-20 16:38:30 -07006412 //Close Watchdog
6413 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6414 vos_watchdog_close(pVosContext);
6415
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306416 //Clean up HDD Nlink Service
6417 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07006418#ifdef WLAN_KD_READY_NOTIFIER
6419 nl_srv_exit(pHddCtx->ptt_pid);
6420#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306421 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006422#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306423
Jeff Johnson295189b2012-06-20 16:38:30 -07006424 /* Cancel the vote for XO Core ON.
6425 * This is done here to ensure there is no race condition since MC, TX and WD threads have
6426 * exited at this point
6427 */
6428 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
6429 " when WLAN is turned OFF\n");
6430 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6431 {
6432 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
6433 " Not returning failure."
6434 " Power consumed will be high\n");
6435 }
6436
6437 hdd_close_all_adapters( pHddCtx );
6438
6439
6440 //Free up dynamically allocated members inside HDD Adapter
6441 kfree(pHddCtx->cfg_ini);
6442 pHddCtx->cfg_ini= NULL;
6443
6444 /* free the power on lock from platform driver */
6445 if (free_riva_power_on_lock("wlan"))
6446 {
6447 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
6448 __func__);
6449 }
6450
Jeff Johnson88ba7742013-02-27 14:36:02 -08006451free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07006452 /* FTM mode, WIPHY did not registered
6453 If un-register here, system crash will happen */
6454 if (VOS_FTM_MODE != hdd_get_conparam())
6455 {
6456 wiphy_unregister(wiphy) ;
6457 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006458 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006459 if (hdd_is_ssr_required())
6460 {
6461 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07006462 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07006463 msleep(5000);
6464 }
6465 hdd_set_ssr_required (VOS_FALSE);
6466}
6467
6468
6469/**---------------------------------------------------------------------------
6470
6471 \brief hdd_update_config_from_nv() - Function to update the contents of
6472 the running configuration with parameters taken from NV storage
6473
6474 \param - pHddCtx - Pointer to the HDD global context
6475
6476 \return - VOS_STATUS_SUCCESS if successful
6477
6478 --------------------------------------------------------------------------*/
6479static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
6480{
Jeff Johnson295189b2012-06-20 16:38:30 -07006481 v_BOOL_t itemIsValid = VOS_FALSE;
6482 VOS_STATUS status;
6483 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
6484 v_U8_t macLoop;
6485
6486 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
6487 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
6488 if(status != VOS_STATUS_SUCCESS)
6489 {
6490 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
6491 return VOS_STATUS_E_FAILURE;
6492 }
6493
6494 if (itemIsValid == VOS_TRUE)
6495 {
6496 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
6497 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
6498 VOS_MAX_CONCURRENCY_PERSONA);
6499 if(status != VOS_STATUS_SUCCESS)
6500 {
6501 /* Get MAC from NV fail, not update CFG info
6502 * INI MAC value will be used for MAC setting */
6503 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
6504 return VOS_STATUS_E_FAILURE;
6505 }
6506
6507 /* If first MAC is not valid, treat all others are not valid
6508 * Then all MACs will be got from ini file */
6509 if(vos_is_macaddr_zero(&macFromNV[0]))
6510 {
6511 /* MAC address in NV file is not configured yet */
6512 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
6513 return VOS_STATUS_E_INVAL;
6514 }
6515
6516 /* Get MAC address from NV, update CFG info */
6517 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
6518 {
6519 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
6520 {
6521 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
6522 /* This MAC is not valid, skip it
6523 * This MAC will be got from ini file */
6524 }
6525 else
6526 {
6527 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
6528 (v_U8_t *)&macFromNV[macLoop].bytes[0],
6529 VOS_MAC_ADDR_SIZE);
6530 }
6531 }
6532 }
6533 else
6534 {
6535 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
6536 return VOS_STATUS_E_FAILURE;
6537 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006538
Jeff Johnson295189b2012-06-20 16:38:30 -07006539
6540 return VOS_STATUS_SUCCESS;
6541}
6542
6543/**---------------------------------------------------------------------------
6544
6545 \brief hdd_post_voss_start_config() - HDD post voss start config helper
6546
6547 \param - pAdapter - Pointer to the HDD
6548
6549 \return - None
6550
6551 --------------------------------------------------------------------------*/
6552VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
6553{
6554 eHalStatus halStatus;
6555 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306556 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07006557
Jeff Johnson295189b2012-06-20 16:38:30 -07006558
6559 // Send ready indication to the HDD. This will kick off the MAC
6560 // into a 'running' state and should kick off an initial scan.
6561 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
6562 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6563 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306564 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07006565 "code %08d [x%08x]",__func__, halStatus, halStatus );
6566 return VOS_STATUS_E_FAILURE;
6567 }
6568
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306569 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07006570 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
6571 // And RIVA will crash
6572 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
6573 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306574 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
6575 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
6576
6577
Jeff Johnson295189b2012-06-20 16:38:30 -07006578 return VOS_STATUS_SUCCESS;
6579}
6580
Jeff Johnson295189b2012-06-20 16:38:30 -07006581/* wake lock APIs for HDD */
6582void hdd_prevent_suspend(void)
6583{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006584#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006585 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006586#else
6587 wcnss_prevent_suspend();
6588#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006589}
6590
6591void hdd_allow_suspend(void)
6592{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006593#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006594 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006595#else
6596 wcnss_allow_suspend();
6597#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006598}
6599
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07006600void hdd_allow_suspend_timeout(v_U32_t timeout)
6601{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006602#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07006603 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07006604#else
6605 /* Do nothing as there is no API in wcnss for timeout*/
6606#endif
6607}
6608
Jeff Johnson295189b2012-06-20 16:38:30 -07006609/**---------------------------------------------------------------------------
6610
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006611 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
6612 information between Host and Riva
6613
6614 This function gets reported version of FW
6615 It also finds the version of Riva headers used to compile the host
6616 It compares the above two and prints a warning if they are different
6617 It gets the SW and HW version string
6618 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
6619 indicating the features they support through a bitmap
6620
6621 \param - pHddCtx - Pointer to HDD context
6622
6623 \return - void
6624
6625 --------------------------------------------------------------------------*/
6626
6627void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
6628{
6629
6630 tSirVersionType versionCompiled;
6631 tSirVersionType versionReported;
6632 tSirVersionString versionString;
6633 tANI_U8 fwFeatCapsMsgSupported = 0;
6634 VOS_STATUS vstatus;
6635
6636 /* retrieve and display WCNSS version information */
6637 do {
6638
6639 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
6640 &versionCompiled);
6641 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6642 {
6643 hddLog(VOS_TRACE_LEVEL_FATAL,
6644 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006645 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006646 break;
6647 }
6648
6649 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
6650 &versionReported);
6651 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6652 {
6653 hddLog(VOS_TRACE_LEVEL_FATAL,
6654 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006655 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006656 break;
6657 }
6658
6659 if ((versionCompiled.major != versionReported.major) ||
6660 (versionCompiled.minor != versionReported.minor) ||
6661 (versionCompiled.version != versionReported.version) ||
6662 (versionCompiled.revision != versionReported.revision))
6663 {
6664 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
6665 "Host expected %u.%u.%u.%u\n",
6666 WLAN_MODULE_NAME,
6667 (int)versionReported.major,
6668 (int)versionReported.minor,
6669 (int)versionReported.version,
6670 (int)versionReported.revision,
6671 (int)versionCompiled.major,
6672 (int)versionCompiled.minor,
6673 (int)versionCompiled.version,
6674 (int)versionCompiled.revision);
6675 }
6676 else
6677 {
6678 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
6679 WLAN_MODULE_NAME,
6680 (int)versionReported.major,
6681 (int)versionReported.minor,
6682 (int)versionReported.version,
6683 (int)versionReported.revision);
6684 }
6685
6686 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
6687 versionString,
6688 sizeof(versionString));
6689 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6690 {
6691 hddLog(VOS_TRACE_LEVEL_FATAL,
6692 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006693 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006694 break;
6695 }
6696
6697 pr_info("%s: WCNSS software version %s\n",
6698 WLAN_MODULE_NAME, versionString);
6699
6700 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
6701 versionString,
6702 sizeof(versionString));
6703 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6704 {
6705 hddLog(VOS_TRACE_LEVEL_FATAL,
6706 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006707 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006708 break;
6709 }
6710
6711 pr_info("%s: WCNSS hardware version %s\n",
6712 WLAN_MODULE_NAME, versionString);
6713
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006714 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
6715 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006716 send the message only if it the riva is 1.1
6717 minor numbers for different riva branches:
6718 0 -> (1.0)Mainline Build
6719 1 -> (1.1)Mainline Build
6720 2->(1.04) Stability Build
6721 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006722 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006723 ((versionReported.minor>=1) && (versionReported.version>=1)))
6724 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
6725 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006726
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006727 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08006728 {
6729#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6730 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
6731 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
6732#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07006733 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
6734 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
6735 {
6736 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
6737 }
6738
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006739 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08006740 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006741
6742 } while (0);
6743
6744}
6745
6746/**---------------------------------------------------------------------------
6747
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05306748 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
6749
6750 \param - pHddCtx - Pointer to the hdd context
6751
6752 \return - true if hardware supports 5GHz
6753
6754 --------------------------------------------------------------------------*/
6755static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
6756{
6757 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
6758 * then hardware support 5Ghz.
6759 */
6760 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
6761 {
6762 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
6763 return true;
6764 }
6765 else
6766 {
6767 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
6768 __func__);
6769 return false;
6770 }
6771}
6772
6773
6774/**---------------------------------------------------------------------------
6775
Jeff Johnson295189b2012-06-20 16:38:30 -07006776 \brief hdd_wlan_startup() - HDD init function
6777
6778 This is the driver startup code executed once a WLAN device has been detected
6779
6780 \param - dev - Pointer to the underlying device
6781
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006782 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07006783
6784 --------------------------------------------------------------------------*/
6785
6786int hdd_wlan_startup(struct device *dev )
6787{
6788 VOS_STATUS status;
6789 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07006790 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006791 hdd_context_t *pHddCtx = NULL;
6792 v_CONTEXT_t pVosContext= NULL;
6793#ifdef WLAN_BTAMP_FEATURE
6794 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
6795 WLANBAP_ConfigType btAmpConfig;
6796 hdd_config_t *pConfig;
6797#endif
6798 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006799 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006800
6801 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006802 /*
6803 * cfg80211: wiphy allocation
6804 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306805 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006806
6807 if(wiphy == NULL)
6808 {
6809 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006810 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006811 }
6812
6813 pHddCtx = wiphy_priv(wiphy);
6814
Jeff Johnson295189b2012-06-20 16:38:30 -07006815 //Initialize the adapter context to zeros.
6816 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
6817
Jeff Johnson295189b2012-06-20 16:38:30 -07006818 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006819 hdd_prevent_suspend();
6820 pHddCtx->isLoadUnloadInProgress = TRUE;
6821
6822 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6823
6824 /*Get vos context here bcoz vos_open requires it*/
6825 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6826
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08006827 if(pVosContext == NULL)
6828 {
6829 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
6830 goto err_free_hdd_context;
6831 }
6832
Jeff Johnson295189b2012-06-20 16:38:30 -07006833 //Save the Global VOSS context in adapter context for future.
6834 pHddCtx->pvosContext = pVosContext;
6835
6836 //Save the adapter context in global context for future.
6837 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
6838
Jeff Johnson295189b2012-06-20 16:38:30 -07006839 pHddCtx->parent_dev = dev;
6840
6841 init_completion(&pHddCtx->full_pwr_comp_var);
6842 init_completion(&pHddCtx->standby_comp_var);
6843 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006844 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08006845 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07006846
6847#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07006848 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07006849#else
6850 init_completion(&pHddCtx->driver_crda_req);
6851#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006852
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05306853 spin_lock_init(&pHddCtx->schedScan_lock);
6854
Jeff Johnson295189b2012-06-20 16:38:30 -07006855 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
6856
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306857#ifdef FEATURE_WLAN_TDLS
6858 /* tdls_lock is initialized before an hdd_open_adapter ( which is
6859 * invoked by other instances also) to protect the concurrent
6860 * access for the Adapters by TDLS module.
6861 */
6862 mutex_init(&pHddCtx->tdls_lock);
6863#endif
6864
Jeff Johnson295189b2012-06-20 16:38:30 -07006865 // Load all config first as TL config is needed during vos_open
6866 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
6867 if(pHddCtx->cfg_ini == NULL)
6868 {
6869 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
6870 goto err_free_hdd_context;
6871 }
6872
6873 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
6874
6875 // Read and parse the qcom_cfg.ini file
6876 status = hdd_parse_config_ini( pHddCtx );
6877 if ( VOS_STATUS_SUCCESS != status )
6878 {
6879 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
6880 __func__, WLAN_INI_FILE);
6881 goto err_config;
6882 }
6883
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05306884 /* INI has been read, initialise the configuredMcastBcastFilter with
6885 * INI value as this will serve as the default value
6886 */
6887 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
6888 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
6889 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05306890
6891 if (false == hdd_is_5g_supported(pHddCtx))
6892 {
6893 //5Ghz is not supported.
6894 if (1 != pHddCtx->cfg_ini->nBandCapability)
6895 {
6896 hddLog(VOS_TRACE_LEVEL_INFO,
6897 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
6898 pHddCtx->cfg_ini->nBandCapability = 1;
6899 }
6900 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05306901
6902 /* If SNR Monitoring is enabled, FW has to parse all beacons
6903 * for calcaluting and storing the average SNR, so set Nth beacon
6904 * filter to 1 to enable FW to parse all the beaocons
6905 */
6906 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
6907 {
6908 /* The log level is deliberately set to WARN as overriding
6909 * nthBeaconFilter to 1 will increase power cosumption and this
6910 * might just prove helpful to detect the power issue.
6911 */
6912 hddLog(VOS_TRACE_LEVEL_WARN,
6913 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
6914 pHddCtx->cfg_ini->nthBeaconFilter = 1;
6915 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006916 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306917 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07006918 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306919 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07006920 {
6921 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306922 "%s: wlan_hdd_cfg80211_init return failure", __func__);
6923 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07006924 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006925
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006926 // Update VOS trace levels based upon the cfg.ini
6927 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
6928 pHddCtx->cfg_ini->vosTraceEnableBAP);
6929 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
6930 pHddCtx->cfg_ini->vosTraceEnableTL);
6931 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
6932 pHddCtx->cfg_ini->vosTraceEnableWDI);
6933 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
6934 pHddCtx->cfg_ini->vosTraceEnableHDD);
6935 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
6936 pHddCtx->cfg_ini->vosTraceEnableSME);
6937 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
6938 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05306939 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
6940 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006941 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
6942 pHddCtx->cfg_ini->vosTraceEnableWDA);
6943 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
6944 pHddCtx->cfg_ini->vosTraceEnableSYS);
6945 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
6946 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006947 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
6948 pHddCtx->cfg_ini->vosTraceEnableSAP);
6949 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
6950 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006951
Jeff Johnson295189b2012-06-20 16:38:30 -07006952 // Update WDI trace levels based upon the cfg.ini
6953 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
6954 pHddCtx->cfg_ini->wdiTraceEnableDAL);
6955 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
6956 pHddCtx->cfg_ini->wdiTraceEnableCTL);
6957 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
6958 pHddCtx->cfg_ini->wdiTraceEnableDAT);
6959 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
6960 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006961
Jeff Johnson88ba7742013-02-27 14:36:02 -08006962 if (VOS_FTM_MODE == hdd_get_conparam())
6963 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006964 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
6965 {
6966 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
6967 goto err_free_hdd_context;
6968 }
6969 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
6970 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08006971 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006972
Jeff Johnson88ba7742013-02-27 14:36:02 -08006973 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07006974 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6975 {
6976 status = vos_watchdog_open(pVosContext,
6977 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
6978
6979 if(!VOS_IS_STATUS_SUCCESS( status ))
6980 {
6981 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306982 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07006983 }
6984 }
6985
6986 pHddCtx->isLogpInProgress = FALSE;
6987 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
6988
Jeff Johnson295189b2012-06-20 16:38:30 -07006989 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
6990 if(!VOS_IS_STATUS_SUCCESS(status))
6991 {
6992 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006993 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07006994 }
6995
Amar Singhala49cbc52013-10-08 18:37:44 -07006996#ifdef CONFIG_ENABLE_LINUX_REG
6997 /* registration of wiphy dev with cfg80211 */
6998 if (0 > wlan_hdd_cfg80211_register(wiphy))
6999 {
7000 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7001 goto err_clkvote;
7002 }
7003#endif
7004
Jeff Johnson295189b2012-06-20 16:38:30 -07007005 status = vos_open( &pVosContext, 0);
7006 if ( !VOS_IS_STATUS_SUCCESS( status ))
7007 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007008 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007009 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007010 }
7011
Jeff Johnson295189b2012-06-20 16:38:30 -07007012 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7013
7014 if ( NULL == pHddCtx->hHal )
7015 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007016 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007017 goto err_vosclose;
7018 }
7019
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007020 status = vos_preStart( pHddCtx->pvosContext );
7021 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7022 {
7023 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7024 goto err_vosclose;
7025 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007026
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007027 /* Note that the vos_preStart() sequence triggers the cfg download.
7028 The cfg download must occur before we update the SME config
7029 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007030 status = hdd_set_sme_config( pHddCtx );
7031
7032 if ( VOS_STATUS_SUCCESS != status )
7033 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007034 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7035 goto err_vosclose;
7036 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007037
7038 //Initialize the WMM module
7039 status = hdd_wmm_init(pHddCtx);
7040 if (!VOS_IS_STATUS_SUCCESS(status))
7041 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007042 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007043 goto err_vosclose;
7044 }
7045
Jeff Johnson295189b2012-06-20 16:38:30 -07007046 /* In the integrated architecture we update the configuration from
7047 the INI file and from NV before vOSS has been started so that
7048 the final contents are available to send down to the cCPU */
7049
7050 // Apply the cfg.ini to cfg.dat
7051 if (FALSE == hdd_update_config_dat(pHddCtx))
7052 {
7053 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7054 goto err_vosclose;
7055 }
7056
7057 // Apply the NV to cfg.dat
7058 /* Prima Update MAC address only at here */
7059 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7060 {
7061#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7062 /* There was not a valid set of MAC Addresses in NV. See if the
7063 default addresses were modified by the cfg.ini settings. If so,
7064 we'll use them, but if not, we'll autogenerate a set of MAC
7065 addresses based upon the device serial number */
7066
7067 static const v_MACADDR_t default_address =
7068 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7069 unsigned int serialno;
7070 int i;
7071
7072 serialno = wcnss_get_serial_number();
7073 if ((0 != serialno) &&
7074 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7075 sizeof(default_address))))
7076 {
7077 /* cfg.ini has the default address, invoke autogen logic */
7078
7079 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7080 bytes of the serial number that can be used to generate
7081 the other 3 bytes of the MAC address. Mask off all but
7082 the lower 3 bytes (this will also make sure we don't
7083 overflow in the next step) */
7084 serialno &= 0x00FFFFFF;
7085
7086 /* we need a unique address for each session */
7087 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7088
7089 /* autogen all addresses */
7090 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7091 {
7092 /* start with the entire default address */
7093 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7094 /* then replace the lower 3 bytes */
7095 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7096 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7097 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7098
7099 serialno++;
7100 }
7101
7102 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7103 MAC_ADDRESS_STR,
7104 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7105 }
7106 else
7107#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7108 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007109 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007110 "%s: Invalid MAC address in NV, using MAC from ini file "
7111 MAC_ADDRESS_STR, __func__,
7112 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7113 }
7114 }
7115 {
7116 eHalStatus halStatus;
7117 // Set the MAC Address
7118 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7119 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7120 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7121 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7122
7123 if (!HAL_STATUS_SUCCESS( halStatus ))
7124 {
7125 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7126 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007127 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007128 }
7129 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007130
7131 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7132 Note: Firmware image will be read and downloaded inside vos_start API */
7133 status = vos_start( pHddCtx->pvosContext );
7134 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7135 {
7136 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7137 goto err_vosclose;
7138 }
7139
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007140 /* Exchange capability info between Host and FW and also get versioning info from FW */
7141 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007142
7143 status = hdd_post_voss_start_config( pHddCtx );
7144 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7145 {
7146 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7147 __func__);
7148 goto err_vosstop;
7149 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007150
7151#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307152 wlan_hdd_cfg80211_update_reg_info( wiphy );
7153
7154 /* registration of wiphy dev with cfg80211 */
7155 if (0 > wlan_hdd_cfg80211_register(wiphy))
7156 {
7157 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7158 goto err_vosstop;
7159 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007160#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007161
Jeff Johnson295189b2012-06-20 16:38:30 -07007162 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7163 {
7164 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7165 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7166 }
7167 else
7168 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007169 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7170 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7171 if (pAdapter != NULL)
7172 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307173 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007174 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307175 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7176 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7177 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007178
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307179 /* Generate the P2P Device Address. This consists of the device's
7180 * primary MAC address with the locally administered bit set.
7181 */
7182 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007183 }
7184 else
7185 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307186 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7187 if (p2p_dev_addr != NULL)
7188 {
7189 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7190 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7191 }
7192 else
7193 {
7194 hddLog(VOS_TRACE_LEVEL_FATAL,
7195 "%s: Failed to allocate mac_address for p2p_device",
7196 __func__);
7197 goto err_close_adapter;
7198 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007199 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007200
7201 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7202 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7203 if ( NULL == pP2pAdapter )
7204 {
7205 hddLog(VOS_TRACE_LEVEL_FATAL,
7206 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007207 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007208 goto err_close_adapter;
7209 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007210 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007211 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007212
7213 if( pAdapter == NULL )
7214 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007215 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7216 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007217 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007218
Jeff Johnson295189b2012-06-20 16:38:30 -07007219#ifdef WLAN_BTAMP_FEATURE
7220 vStatus = WLANBAP_Open(pVosContext);
7221 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7222 {
7223 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7224 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007225 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007226 }
7227
7228 vStatus = BSL_Init(pVosContext);
7229 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7230 {
7231 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7232 "%s: Failed to Init BSL",__func__);
7233 goto err_bap_close;
7234 }
7235 vStatus = WLANBAP_Start(pVosContext);
7236 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7237 {
7238 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7239 "%s: Failed to start TL",__func__);
7240 goto err_bap_close;
7241 }
7242
7243 pConfig = pHddCtx->cfg_ini;
7244 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7245 status = WLANBAP_SetConfig(&btAmpConfig);
7246
7247#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007248
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007249#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7250 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7251 {
7252 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7253 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7254 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7255 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7256 }
7257#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007258#ifdef FEATURE_WLAN_SCAN_PNO
7259 /*SME must send channel update configuration to RIVA*/
7260 sme_UpdateChannelConfig(pHddCtx->hHal);
7261#endif
7262
Jeff Johnson295189b2012-06-20 16:38:30 -07007263 /* Register with platform driver as client for Suspend/Resume */
7264 status = hddRegisterPmOps(pHddCtx);
7265 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7266 {
7267 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7268#ifdef WLAN_BTAMP_FEATURE
7269 goto err_bap_stop;
7270#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007271 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007272#endif //WLAN_BTAMP_FEATURE
7273 }
7274
Yue Ma0d4891e2013-08-06 17:01:45 -07007275 /* Open debugfs interface */
7276 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
7277 {
7278 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7279 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07007280 }
7281
Jeff Johnson295189b2012-06-20 16:38:30 -07007282 /* Register TM level change handler function to the platform */
7283 status = hddDevTmRegisterNotifyCallback(pHddCtx);
7284 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7285 {
7286 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
7287 goto err_unregister_pmops;
7288 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007289
7290 /* register for riva power on lock to platform driver */
7291 if (req_riva_power_on_lock("wlan"))
7292 {
7293 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
7294 __func__);
7295 goto err_unregister_pmops;
7296 }
7297
Jeff Johnson295189b2012-06-20 16:38:30 -07007298 // register net device notifier for device change notification
7299 ret = register_netdevice_notifier(&hdd_netdev_notifier);
7300
7301 if(ret < 0)
7302 {
7303 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
7304 goto err_free_power_on_lock;
7305 }
7306
7307 //Initialize the nlink service
7308 if(nl_srv_init() != 0)
7309 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307310 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007311 goto err_reg_netdev;
7312 }
7313
7314 //Initialize the BTC service
7315 if(btc_activate_service(pHddCtx) != 0)
7316 {
7317 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
7318 goto err_nl_srv;
7319 }
7320
7321#ifdef PTT_SOCK_SVC_ENABLE
7322 //Initialize the PTT service
7323 if(ptt_sock_activate_svc(pHddCtx) != 0)
7324 {
7325 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
7326 goto err_nl_srv;
7327 }
7328#endif
7329
Jeff Johnson295189b2012-06-20 16:38:30 -07007330 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007331 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007332 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07007333 /* Action frame registered in one adapter which will
7334 * applicable to all interfaces
7335 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07007336 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007337 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007338
7339 mutex_init(&pHddCtx->sap_lock);
7340
7341 pHddCtx->isLoadUnloadInProgress = FALSE;
7342
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007343#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007344#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7345 /* Initialize the wake lcok */
7346 wake_lock_init(&pHddCtx->rx_wake_lock,
7347 WAKE_LOCK_SUSPEND,
7348 "qcom_rx_wakelock");
7349#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007350 /* Initialize the wake lcok */
7351 wake_lock_init(&pHddCtx->sap_wake_lock,
7352 WAKE_LOCK_SUSPEND,
7353 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007354#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007355
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007356 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
7357 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07007358
7359 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7360 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05307361
Jeff Johnsone7245742012-09-05 17:12:55 -07007362 // Initialize the restart logic
7363 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05307364
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007365 //Register the traffic monitor timer now
7366 if ( pHddCtx->cfg_ini->dynSplitscan)
7367 {
7368 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
7369 VOS_TIMER_TYPE_SW,
7370 hdd_tx_rx_pkt_cnt_stat_timer_handler,
7371 (void *)pHddCtx);
7372 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007373 goto success;
7374
7375err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07007376#ifdef WLAN_KD_READY_NOTIFIER
7377 nl_srv_exit(pHddCtx->ptt_pid);
7378#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007379 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007380#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07007381err_reg_netdev:
7382 unregister_netdevice_notifier(&hdd_netdev_notifier);
7383
7384err_free_power_on_lock:
7385 free_riva_power_on_lock("wlan");
7386
7387err_unregister_pmops:
7388 hddDevTmUnregisterNotifyCallback(pHddCtx);
7389 hddDeregisterPmOps(pHddCtx);
7390
Yue Ma0d4891e2013-08-06 17:01:45 -07007391 hdd_debugfs_exit(pHddCtx);
7392
Jeff Johnson295189b2012-06-20 16:38:30 -07007393#ifdef WLAN_BTAMP_FEATURE
7394err_bap_stop:
7395 WLANBAP_Stop(pVosContext);
7396#endif
7397
7398#ifdef WLAN_BTAMP_FEATURE
7399err_bap_close:
7400 WLANBAP_Close(pVosContext);
7401#endif
7402
Jeff Johnson295189b2012-06-20 16:38:30 -07007403err_close_adapter:
7404 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07007405
7406#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307407 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07007408#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007409
7410err_vosstop:
7411 vos_stop(pVosContext);
7412
Amar Singhala49cbc52013-10-08 18:37:44 -07007413err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07007414 status = vos_sched_close( pVosContext );
7415 if (!VOS_IS_STATUS_SUCCESS(status)) {
7416 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7417 "%s: Failed to close VOSS Scheduler", __func__);
7418 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
7419 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007420 vos_close(pVosContext );
7421
7422err_wiphy_unregister:
7423
7424#ifdef CONFIG_ENABLE_LINUX_REG
7425 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07007426
Jeff Johnson295189b2012-06-20 16:38:30 -07007427err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07007428#endif
7429
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007430 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007431
7432err_wdclose:
7433 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7434 vos_watchdog_close(pVosContext);
7435
Jeff Johnson295189b2012-06-20 16:38:30 -07007436err_config:
7437 kfree(pHddCtx->cfg_ini);
7438 pHddCtx->cfg_ini= NULL;
7439
7440err_free_hdd_context:
7441 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07007442 wiphy_free(wiphy) ;
7443 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007444 VOS_BUG(1);
7445
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08007446 if (hdd_is_ssr_required())
7447 {
7448 /* WDI timeout had happened during load, so SSR is needed here */
7449 subsystem_restart("wcnss");
7450 msleep(5000);
7451 }
7452 hdd_set_ssr_required (VOS_FALSE);
7453
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007454 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007455
7456success:
7457 EXIT();
7458 return 0;
7459}
7460
7461/**---------------------------------------------------------------------------
7462
Jeff Johnson32d95a32012-09-10 13:15:23 -07007463 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07007464
Jeff Johnson32d95a32012-09-10 13:15:23 -07007465 This is the driver entry point - called in different timeline depending
7466 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07007467
7468 \param - None
7469
7470 \return - 0 for success, non zero for failure
7471
7472 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07007473static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007474{
7475 VOS_STATUS status;
7476 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007477 struct device *dev = NULL;
7478 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007479#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7480 int max_retries = 0;
7481#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007482
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307483#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7484 vos_wconn_trace_init();
7485#endif
7486
Jeff Johnson295189b2012-06-20 16:38:30 -07007487 ENTER();
7488
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007489#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007490 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07007491#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007492
7493 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
7494 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
7495
7496 //Power Up Libra WLAN card first if not already powered up
7497 status = vos_chipPowerUp(NULL,NULL,NULL);
7498 if (!VOS_IS_STATUS_SUCCESS(status))
7499 {
7500 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
7501 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307502#ifdef WLAN_OPEN_SOURCE
7503 wake_lock_destroy(&wlan_wake_lock);
7504#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007505 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007506 }
7507
Jeff Johnson295189b2012-06-20 16:38:30 -07007508#ifdef ANI_BUS_TYPE_PCI
7509
7510 dev = wcnss_wlan_get_device();
7511
7512#endif // ANI_BUS_TYPE_PCI
7513
7514#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007515
7516#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7517 /* wait until WCNSS driver downloads NV */
7518 while (!wcnss_device_ready() && 5 >= ++max_retries) {
7519 msleep(1000);
7520 }
7521 if (max_retries >= 5) {
7522 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307523#ifdef WLAN_OPEN_SOURCE
7524 wake_lock_destroy(&wlan_wake_lock);
7525#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007526 return -ENODEV;
7527 }
7528#endif
7529
Jeff Johnson295189b2012-06-20 16:38:30 -07007530 dev = wcnss_wlan_get_device();
7531#endif // ANI_BUS_TYPE_PLATFORM
7532
7533
7534 do {
7535 if (NULL == dev) {
7536 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
7537 ret_status = -1;
7538 break;
7539 }
7540
7541#ifdef MEMORY_DEBUG
7542 vos_mem_init();
7543#endif
7544
7545#ifdef TIMER_MANAGER
7546 vos_timer_manager_init();
7547#endif
7548
7549 /* Preopen VOSS so that it is ready to start at least SAL */
7550 status = vos_preOpen(&pVosContext);
7551
7552 if (!VOS_IS_STATUS_SUCCESS(status))
7553 {
7554 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
7555 ret_status = -1;
7556 break;
7557 }
7558
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007559#ifndef MODULE
7560 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
7561 */
7562 hdd_set_conparam((v_UINT_t)con_mode);
7563#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007564
7565 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007566 if (hdd_wlan_startup(dev))
7567 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007568 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007569 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007570 vos_preClose( &pVosContext );
7571 ret_status = -1;
7572 break;
7573 }
7574
7575 /* Cancel the vote for XO Core ON
7576 * This is done here for safety purposes in case we re-initialize without turning
7577 * it OFF in any error scenario.
7578 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007579 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07007580 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007581 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07007582 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7583 {
7584 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
7585 " Power consumed will be high\n");
7586 }
7587 } while (0);
7588
7589 if (0 != ret_status)
7590 {
7591 //Assert Deep sleep signal now to put Libra HW in lowest power state
7592 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7593 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
7594
7595 //Vote off any PMIC voltage supplies
7596 vos_chipPowerDown(NULL, NULL, NULL);
7597#ifdef TIMER_MANAGER
7598 vos_timer_exit();
7599#endif
7600#ifdef MEMORY_DEBUG
7601 vos_mem_exit();
7602#endif
7603
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007604#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007605 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007606#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007607 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
7608 }
7609 else
7610 {
7611 //Send WLAN UP indication to Nlink Service
7612 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
7613
7614 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07007615 }
7616
7617 EXIT();
7618
7619 return ret_status;
7620}
7621
Jeff Johnson32d95a32012-09-10 13:15:23 -07007622/**---------------------------------------------------------------------------
7623
7624 \brief hdd_module_init() - Init Function
7625
7626 This is the driver entry point (invoked when module is loaded using insmod)
7627
7628 \param - None
7629
7630 \return - 0 for success, non zero for failure
7631
7632 --------------------------------------------------------------------------*/
7633#ifdef MODULE
7634static int __init hdd_module_init ( void)
7635{
7636 return hdd_driver_init();
7637}
Jeff Johnson32d95a32012-09-10 13:15:23 -07007638#else /* #ifdef MODULE */
7639static int __init hdd_module_init ( void)
7640{
7641 /* Driver initialization is delayed to fwpath_changed_handler */
7642 return 0;
7643}
Jeff Johnson32d95a32012-09-10 13:15:23 -07007644#endif /* #ifdef MODULE */
7645
Jeff Johnson295189b2012-06-20 16:38:30 -07007646
7647/**---------------------------------------------------------------------------
7648
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007649 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007650
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007651 This is the driver exit point (invoked when module is unloaded using rmmod
7652 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07007653
7654 \param - None
7655
7656 \return - None
7657
7658 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007659static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007660{
7661 hdd_context_t *pHddCtx = NULL;
7662 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007663 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007664
7665 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
7666
7667 //Get the global vos context
7668 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7669
7670 if(!pVosContext)
7671 {
7672 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
7673 goto done;
7674 }
7675
7676 //Get the HDD context.
7677 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
7678
7679 if(!pHddCtx)
7680 {
7681 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
7682 }
7683 else
7684 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007685 while(isWDresetInProgress()) {
7686 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7687 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007688 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007689
7690 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
7691 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7692 "%s:SSR never completed, fatal error", __func__);
7693 VOS_BUG(0);
7694 }
7695 }
7696
Jeff Johnson295189b2012-06-20 16:38:30 -07007697
7698 pHddCtx->isLoadUnloadInProgress = TRUE;
7699 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7700
7701 //Do all the cleanup before deregistering the driver
7702 hdd_wlan_exit(pHddCtx);
7703 }
7704
Jeff Johnson295189b2012-06-20 16:38:30 -07007705 vos_preClose( &pVosContext );
7706
7707#ifdef TIMER_MANAGER
7708 vos_timer_exit();
7709#endif
7710#ifdef MEMORY_DEBUG
7711 vos_mem_exit();
7712#endif
7713
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307714#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7715 vos_wconn_trace_exit();
7716#endif
7717
Jeff Johnson295189b2012-06-20 16:38:30 -07007718done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007719#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007720 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007721#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007722 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
7723}
7724
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007725/**---------------------------------------------------------------------------
7726
7727 \brief hdd_module_exit() - Exit function
7728
7729 This is the driver exit point (invoked when module is unloaded using rmmod)
7730
7731 \param - None
7732
7733 \return - None
7734
7735 --------------------------------------------------------------------------*/
7736static void __exit hdd_module_exit(void)
7737{
7738 hdd_driver_exit();
7739}
7740
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007741#ifdef MODULE
7742static int fwpath_changed_handler(const char *kmessage,
7743 struct kernel_param *kp)
7744{
Jeff Johnson76052702013-04-16 13:55:05 -07007745 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007746}
7747
7748static int con_mode_handler(const char *kmessage,
7749 struct kernel_param *kp)
7750{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07007751 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007752}
7753#else /* #ifdef MODULE */
7754/**---------------------------------------------------------------------------
7755
Jeff Johnson76052702013-04-16 13:55:05 -07007756 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007757
Jeff Johnson76052702013-04-16 13:55:05 -07007758 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007759 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07007760 - invoked when module parameter fwpath is modified from userspace to signal
7761 initializing the WLAN driver or when con_mode is modified from userspace
7762 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007763
7764 \return - 0 for success, non zero for failure
7765
7766 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07007767static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007768{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007769 int ret_status;
7770
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007771 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007772 ret_status = hdd_driver_init();
7773 wlan_hdd_inited = ret_status ? 0 : 1;
7774 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007775 }
7776
7777 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07007778
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007779 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07007780
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007781 ret_status = hdd_driver_init();
7782 wlan_hdd_inited = ret_status ? 0 : 1;
7783 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007784}
7785
Jeff Johnson295189b2012-06-20 16:38:30 -07007786/**---------------------------------------------------------------------------
7787
Jeff Johnson76052702013-04-16 13:55:05 -07007788 \brief fwpath_changed_handler() - Handler Function
7789
7790 Handle changes to the fwpath parameter
7791
7792 \return - 0 for success, non zero for failure
7793
7794 --------------------------------------------------------------------------*/
7795static int fwpath_changed_handler(const char *kmessage,
7796 struct kernel_param *kp)
7797{
7798 int ret;
7799
7800 ret = param_set_copystring(kmessage, kp);
7801 if (0 == ret)
7802 ret = kickstart_driver();
7803 return ret;
7804}
7805
7806/**---------------------------------------------------------------------------
7807
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007808 \brief con_mode_handler() -
7809
7810 Handler function for module param con_mode when it is changed by userspace
7811 Dynamically linked - do nothing
7812 Statically linked - exit and init driver, as in rmmod and insmod
7813
Jeff Johnson76052702013-04-16 13:55:05 -07007814 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007815
Jeff Johnson76052702013-04-16 13:55:05 -07007816 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007817
7818 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07007819static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007820{
Jeff Johnson76052702013-04-16 13:55:05 -07007821 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007822
Jeff Johnson76052702013-04-16 13:55:05 -07007823 ret = param_set_int(kmessage, kp);
7824 if (0 == ret)
7825 ret = kickstart_driver();
7826 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007827}
7828#endif /* #ifdef MODULE */
7829
7830/**---------------------------------------------------------------------------
7831
Jeff Johnson295189b2012-06-20 16:38:30 -07007832 \brief hdd_get_conparam() -
7833
7834 This is the driver exit point (invoked when module is unloaded using rmmod)
7835
7836 \param - None
7837
7838 \return - tVOS_CON_MODE
7839
7840 --------------------------------------------------------------------------*/
7841tVOS_CON_MODE hdd_get_conparam ( void )
7842{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007843#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07007844 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007845#else
7846 return (tVOS_CON_MODE)curr_con_mode;
7847#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007848}
7849void hdd_set_conparam ( v_UINT_t newParam )
7850{
7851 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007852#ifndef MODULE
7853 curr_con_mode = con_mode;
7854#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007855}
7856/**---------------------------------------------------------------------------
7857
7858 \brief hdd_softap_sta_deauth() - function
7859
7860 This to take counter measure to handle deauth req from HDD
7861
7862 \param - pAdapter - Pointer to the HDD
7863
7864 \param - enable - boolean value
7865
7866 \return - None
7867
7868 --------------------------------------------------------------------------*/
7869
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007870VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07007871{
Jeff Johnson295189b2012-06-20 16:38:30 -07007872 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007873 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07007874
7875 ENTER();
7876
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007877 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
7878 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007879
7880 //Ignore request to deauth bcmc station
7881 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007882 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07007883
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007884 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07007885
7886 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007887 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07007888}
7889
7890/**---------------------------------------------------------------------------
7891
7892 \brief hdd_softap_sta_disassoc() - function
7893
7894 This to take counter measure to handle deauth req from HDD
7895
7896 \param - pAdapter - Pointer to the HDD
7897
7898 \param - enable - boolean value
7899
7900 \return - None
7901
7902 --------------------------------------------------------------------------*/
7903
7904void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
7905{
7906 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
7907
7908 ENTER();
7909
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307910 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007911
7912 //Ignore request to disassoc bcmc station
7913 if( pDestMacAddress[0] & 0x1 )
7914 return;
7915
7916 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
7917}
7918
7919void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
7920{
7921 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
7922
7923 ENTER();
7924
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307925 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007926
7927 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
7928}
7929
Jeff Johnson295189b2012-06-20 16:38:30 -07007930/**---------------------------------------------------------------------------
7931 *
7932 * \brief hdd_get__concurrency_mode() -
7933 *
7934 *
7935 * \param - None
7936 *
7937 * \return - CONCURRENCY MODE
7938 *
7939 * --------------------------------------------------------------------------*/
7940tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
7941{
7942 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
7943 hdd_context_t *pHddCtx;
7944
7945 if (NULL != pVosContext)
7946 {
7947 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
7948 if (NULL != pHddCtx)
7949 {
7950 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
7951 }
7952 }
7953
7954 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007955 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007956 return VOS_STA;
7957}
7958
7959/* Decide whether to allow/not the apps power collapse.
7960 * Allow apps power collapse if we are in connected state.
7961 * if not, allow only if we are in IMPS */
7962v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
7963{
7964 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08007965 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08007966 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07007967 hdd_config_t *pConfig = pHddCtx->cfg_ini;
7968 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7969 hdd_adapter_t *pAdapter = NULL;
7970 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08007971 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007972
Jeff Johnson295189b2012-06-20 16:38:30 -07007973 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7974 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007975
Yathish9f22e662012-12-10 14:21:35 -08007976 concurrent_state = hdd_get_concurrency_mode();
7977
7978#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7979 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
7980 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
7981 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
7982 return TRUE;
7983#endif
7984
Jeff Johnson295189b2012-06-20 16:38:30 -07007985 /*loop through all adapters. TBD fix for Concurrency */
7986 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7987 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7988 {
7989 pAdapter = pAdapterNode->pAdapter;
7990 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
7991 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7992 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08007993 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07007994 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08007995 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08007996 (eANI_BOOLEAN_TRUE == scanRspPending) ||
7997 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07007998 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08007999 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008000 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8001 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008002 return FALSE;
8003 }
8004 }
8005 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8006 pAdapterNode = pNext;
8007 }
8008 return TRUE;
8009}
8010
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008011/* Decides whether to send suspend notification to Riva
8012 * if any adapter is in BMPS; then it is required */
8013v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8014{
8015 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8016 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8017
8018 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8019 {
8020 return TRUE;
8021 }
8022 return FALSE;
8023}
8024
Jeff Johnson295189b2012-06-20 16:38:30 -07008025void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8026{
8027 switch(mode)
8028 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008029 case VOS_STA_MODE:
8030 case VOS_P2P_CLIENT_MODE:
8031 case VOS_P2P_GO_MODE:
8032 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008033 pHddCtx->concurrency_mode |= (1 << mode);
8034 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008035 break;
8036 default:
8037 break;
8038
8039 }
8040 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8041 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8042}
8043
8044
8045void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8046{
8047 switch(mode)
8048 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008049 case VOS_STA_MODE:
8050 case VOS_P2P_CLIENT_MODE:
8051 case VOS_P2P_GO_MODE:
8052 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008053 pHddCtx->no_of_sessions[mode]--;
8054 if (!(pHddCtx->no_of_sessions[mode]))
8055 pHddCtx->concurrency_mode &= (~(1 << mode));
8056 break;
8057 default:
8058 break;
8059 }
8060 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8061 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8062}
8063
Jeff Johnsone7245742012-09-05 17:12:55 -07008064/**---------------------------------------------------------------------------
8065 *
8066 * \brief wlan_hdd_restart_init
8067 *
8068 * This function initalizes restart timer/flag. An internal function.
8069 *
8070 * \param - pHddCtx
8071 *
8072 * \return - None
8073 *
8074 * --------------------------------------------------------------------------*/
8075
8076static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8077{
8078 /* Initialize */
8079 pHddCtx->hdd_restart_retries = 0;
8080 atomic_set(&pHddCtx->isRestartInProgress, 0);
8081 vos_timer_init(&pHddCtx->hdd_restart_timer,
8082 VOS_TIMER_TYPE_SW,
8083 wlan_hdd_restart_timer_cb,
8084 pHddCtx);
8085}
8086/**---------------------------------------------------------------------------
8087 *
8088 * \brief wlan_hdd_restart_deinit
8089 *
8090 * This function cleans up the resources used. An internal function.
8091 *
8092 * \param - pHddCtx
8093 *
8094 * \return - None
8095 *
8096 * --------------------------------------------------------------------------*/
8097
8098static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8099{
8100
8101 VOS_STATUS vos_status;
8102 /* Block any further calls */
8103 atomic_set(&pHddCtx->isRestartInProgress, 1);
8104 /* Cleanup */
8105 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8106 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008107 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008108 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8109 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008110 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008111
8112}
8113
8114/**---------------------------------------------------------------------------
8115 *
8116 * \brief wlan_hdd_framework_restart
8117 *
8118 * This function uses a cfg80211 API to start a framework initiated WLAN
8119 * driver module unload/load.
8120 *
8121 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8122 *
8123 *
8124 * \param - pHddCtx
8125 *
8126 * \return - VOS_STATUS_SUCCESS: Success
8127 * VOS_STATUS_E_EMPTY: Adapter is Empty
8128 * VOS_STATUS_E_NOMEM: No memory
8129
8130 * --------------------------------------------------------------------------*/
8131
8132static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8133{
8134 VOS_STATUS status = VOS_STATUS_SUCCESS;
8135 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008136 int len = (sizeof (struct ieee80211_mgmt));
8137 struct ieee80211_mgmt *mgmt = NULL;
8138
8139 /* Prepare the DEAUTH managment frame with reason code */
8140 mgmt = kzalloc(len, GFP_KERNEL);
8141 if(mgmt == NULL)
8142 {
8143 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8144 "%s: memory allocation failed (%d bytes)", __func__, len);
8145 return VOS_STATUS_E_NOMEM;
8146 }
8147 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008148
8149 /* Iterate over all adapters/devices */
8150 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8151 do
8152 {
8153 if( (status == VOS_STATUS_SUCCESS) &&
8154 pAdapterNode &&
8155 pAdapterNode->pAdapter)
8156 {
8157 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8158 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8159 pAdapterNode->pAdapter->dev->name,
8160 pAdapterNode->pAdapter->device_mode,
8161 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008162 /*
8163 * CFG80211 event to restart the driver
8164 *
8165 * 'cfg80211_send_unprot_deauth' sends a
8166 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8167 * of SME(Linux Kernel) state machine.
8168 *
8169 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8170 * the driver.
8171 *
8172 */
8173
8174 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008175 }
8176 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8177 pAdapterNode = pNext;
8178 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8179
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008180
8181 /* Free the allocated management frame */
8182 kfree(mgmt);
8183
Jeff Johnsone7245742012-09-05 17:12:55 -07008184 /* Retry until we unload or reach max count */
8185 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8186 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8187
8188 return status;
8189
8190}
8191/**---------------------------------------------------------------------------
8192 *
8193 * \brief wlan_hdd_restart_timer_cb
8194 *
8195 * Restart timer callback. An internal function.
8196 *
8197 * \param - User data:
8198 *
8199 * \return - None
8200 *
8201 * --------------------------------------------------------------------------*/
8202
8203void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8204{
8205 hdd_context_t *pHddCtx = usrDataForCallback;
8206 wlan_hdd_framework_restart(pHddCtx);
8207 return;
8208
8209}
8210
8211
8212/**---------------------------------------------------------------------------
8213 *
8214 * \brief wlan_hdd_restart_driver
8215 *
8216 * This function sends an event to supplicant to restart the WLAN driver.
8217 *
8218 * This function is called from vos_wlanRestart.
8219 *
8220 * \param - pHddCtx
8221 *
8222 * \return - VOS_STATUS_SUCCESS: Success
8223 * VOS_STATUS_E_EMPTY: Adapter is Empty
8224 * VOS_STATUS_E_ALREADY: Request already in progress
8225
8226 * --------------------------------------------------------------------------*/
8227VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8228{
8229 VOS_STATUS status = VOS_STATUS_SUCCESS;
8230
8231 /* A tight check to make sure reentrancy */
8232 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8233 {
8234 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8235 "%s: WLAN restart is already in progress", __func__);
8236
8237 return VOS_STATUS_E_ALREADY;
8238 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008239 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008240#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008241 wcnss_reset_intr();
8242#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008243
Jeff Johnsone7245742012-09-05 17:12:55 -07008244 return status;
8245}
8246
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008247/*
8248 * API to find if there is any STA or P2P-Client is connected
8249 */
8250VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8251{
8252 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8253}
Jeff Johnsone7245742012-09-05 17:12:55 -07008254
Jeff Johnson295189b2012-06-20 16:38:30 -07008255//Register the module init/exit functions
8256module_init(hdd_module_init);
8257module_exit(hdd_module_exit);
8258
8259MODULE_LICENSE("Dual BSD/GPL");
8260MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8261MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8262
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008263module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8264 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008265
Jeff Johnson76052702013-04-16 13:55:05 -07008266module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07008267 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);