blob: a7afa2c844c8a241003e8ec6e01cfa3354623301 [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;
987 tANI_U32 numberScanList;
988 tANI_U32 nextScanListOffset;
989 tANI_U32 nextApMetaInfoOffset;
990 hdd_adapter_t* pAdapter;
991 tpSirBatchScanList pScanList;
992 tpSirBatchScanNetworkInfo pApMetaInfo;
993 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
994 tSirSetBatchScanReq *pReq;
995
996 pAdapter = (hdd_adapter_t *)callbackContext;
997 /*sanity check*/
998 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
999 {
1000 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1001 "%s: Invalid pAdapter magic", __func__);
1002 VOS_ASSERT(0);
1003 return;
1004 }
1005
1006 /*initialize locals*/
1007 pReq = &pAdapter->hddSetBatchScanReq;
1008 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1009 isLastAp = FALSE;
1010 numApMetaInfo = 0;
1011 numberScanList = 0;
1012 nextScanListOffset = 0;
1013 nextApMetaInfoOffset = 0;
1014 pScanList = NULL;
1015 pApMetaInfo = NULL;
1016
1017 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1018 {
1019 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1020 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1021 isLastAp = TRUE;
1022 goto done;
1023 }
1024
1025 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1026 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1027 "Batch scan rsp: numberScalList %d", numberScanList);
1028
1029 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1030 {
1031 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1032 "%s: numberScanList %d", __func__, numberScanList);
1033 isLastAp = TRUE;
1034 goto done;
1035 }
1036
1037 while (numberScanList)
1038 {
1039 pScanList = (tpSirBatchScanList)(pBatchScanRsp->scanResults +
1040 nextScanListOffset);
1041 if (NULL == pScanList)
1042 {
1043 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1044 "%s: pScanList is %p", __func__, pScanList);
1045 isLastAp = TRUE;
1046 goto done;
1047 }
1048 numApMetaInfo = pScanList->numNetworksInScanList;
1049 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1050 "Batch scan rsp: numApMetaInfo %d", numApMetaInfo);
1051
1052 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1053 {
1054 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1055 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1056 isLastAp = TRUE;
1057 goto done;
1058 }
1059
1060 while (numApMetaInfo)
1061 {
1062 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1063 nextApMetaInfoOffset);
1064 if (NULL == pApMetaInfo)
1065 {
1066 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1067 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1068 isLastAp = TRUE;
1069 goto done;
1070 }
1071 /*calculate AP age*/
1072 pApMetaInfo->timestamp =
1073 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1074
1075 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1076 "%s: bssId 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x "
1077 "ch %d rssi %d timestamp %d", __func__,
1078 pApMetaInfo->bssid[0],pApMetaInfo->bssid[1],
1079 pApMetaInfo->bssid[2],pApMetaInfo->bssid[3],
1080 pApMetaInfo->bssid[4],pApMetaInfo->bssid[5],
1081 pApMetaInfo->ch, pApMetaInfo->rssi,
1082 pApMetaInfo->timestamp);
1083
1084 /*mark last AP in batch scan response*/
1085 if ((TRUE == pBatchScanRsp->isLastResult) &&
1086 (1 == numberScanList) && (1 == numApMetaInfo))
1087 {
1088 isLastAp = TRUE;
1089 }
1090
1091 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1092 /*store batch scan repsonse in hdd queue*/
1093 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1094 pScanList->scanId, isLastAp);
1095 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1096
1097 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1098 numApMetaInfo--;
1099 }
1100
1101 nextScanListOffset += (sizeof(tSirBatchScanList) - (sizeof(tANI_U8)));
1102 numberScanList--;
1103 }
1104
1105done:
1106
1107 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1108 requested from hdd_ioctl*/
1109 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1110 (TRUE == isLastAp))
1111 {
1112 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1113 complete(&pAdapter->hdd_get_batch_scan_req_var);
1114 }
1115
1116 return;
1117}/*End of hdd_batch_scan_result_ind_callback*/
1118
1119/**---------------------------------------------------------------------------
1120
1121 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1122 response as per batch scan FR request format by putting proper markers
1123
1124 \param - pDest pointer to destination buffer
1125 \param - cur_len current length
1126 \param - tot_len total remaining size which can be written to user space
1127 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1128 \param - pAdapter Pointer to HDD adapter
1129
1130 \return - ret no of characters written
1131
1132 --------------------------------------------------------------------------*/
1133static tANI_U32
1134hdd_format_batch_scan_rsp
1135(
1136 tANI_U8 *pDest,
1137 tANI_U32 cur_len,
1138 tANI_U32 tot_len,
1139 tHddBatchScanRsp *pApMetaInfo,
1140 hdd_adapter_t* pAdapter
1141)
1142{
1143 tANI_U32 ret = 0;
1144 tANI_U32 rem_len = 0;
1145 tANI_U8 temp_len = 0;
1146 tANI_U8 temp_total_len = 0;
1147 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1148 tANI_U8 *pTemp = temp;
1149
1150 /*Batch scan reponse needs to be returned to user space in
1151 following format:
1152 "scancount=X\n" where X is the number of scans in current batch
1153 batch
1154 "trunc\n" optional present if current scan truncated
1155 "bssid=XX:XX:XX:XX:XX:XX\n"
1156 "ssid=XXXX\n"
1157 "freq=X\n" frequency in Mhz
1158 "level=XX\n"
1159 "age=X\n" ms
1160 "dist=X\n" cm (-1 if not available)
1161 "errror=X\n" (-1if not available)
1162 "====\n" (end of ap marker)
1163 "####\n" (end of scan marker)
1164 "----\n" (end of results)*/
1165 /*send scan result in above format to user space based on
1166 available length*/
1167 /*The GET response may have more data than the driver can return in its
1168 buffer. In that case the buffer should be filled to the nearest complete
1169 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1170 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1171 The final buffer should end with "----\n"*/
1172
1173 /*sanity*/
1174 if (cur_len > tot_len)
1175 {
1176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1177 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1178 return 0;
1179 }
1180 else
1181 {
1182 rem_len = (tot_len - cur_len);
1183 }
1184
1185 /*end scan marker*/
1186 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1187 {
1188 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1189 pTemp += temp_len;
1190 temp_total_len += temp_len;
1191 }
1192
1193 /*bssid*/
1194 temp_len = snprintf(pTemp, sizeof(temp),
1195 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1196 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1197 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1198 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1199 pTemp += temp_len;
1200 temp_total_len += temp_len;
1201
1202 /*ssid*/
1203 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1204 pApMetaInfo->ApInfo.ssid);
1205 pTemp += temp_len;
1206 temp_total_len += temp_len;
1207
1208 /*freq*/
1209 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
1210 pApMetaInfo->ApInfo.ch);
1211 pTemp += temp_len;
1212 temp_total_len += temp_len;
1213
1214 /*level*/
1215 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1216 pApMetaInfo->ApInfo.rssi);
1217 pTemp += temp_len;
1218 temp_total_len += temp_len;
1219
1220 /*age*/
1221 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%ld\n",
1222 pApMetaInfo->ApInfo.age);
1223 pTemp += temp_len;
1224 temp_total_len += temp_len;
1225
1226 /*dist*/
1227 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1228 pTemp += temp_len;
1229 temp_total_len += temp_len;
1230
1231 /*error*/
1232 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1233 pTemp += temp_len;
1234 temp_total_len += temp_len;
1235
1236 /*end AP marker*/
1237 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1238 pTemp += temp_len;
1239 temp_total_len += temp_len;
1240
1241 /*last AP in batch scan response*/
1242 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1243 {
1244 /*end scan marker*/
1245 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1246 pTemp += temp_len;
1247 temp_total_len += temp_len;
1248
1249 /*end batch scan result marker*/
1250 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1251 pTemp += temp_len;
1252 temp_total_len += temp_len;
1253 }
1254
1255 if (temp_total_len < rem_len)
1256 {
1257 ret = temp_total_len + 1;
1258 strlcpy(pDest, temp, ret);
1259 pAdapter->isTruncated = FALSE;
1260 }
1261 else
1262 {
1263 pAdapter->isTruncated = TRUE;
1264 if (rem_len >= strlen("%%%%"))
1265 {
1266 ret = snprintf(pDest, strlen("%%%%"), "%%%%");
1267 }
1268 {
1269 ret = 0;
1270 }
1271 }
1272
1273 return ret;
1274
1275}/*End of hdd_format_batch_scan_rsp*/
1276
1277/**---------------------------------------------------------------------------
1278
1279 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1280 buffer starting with head of hdd batch scan response queue
1281
1282 \param - pAdapter Pointer to HDD adapter
1283 \param - pDest Pointer to user data buffer
1284 \param - cur_len current offset in user buffer
1285 \param - rem_len remaining no of bytes in user buffer
1286
1287 \return - number of bytes written in user buffer
1288
1289 --------------------------------------------------------------------------*/
1290
1291tANI_U32 hdd_populate_user_batch_scan_rsp
1292(
1293 hdd_adapter_t* pAdapter,
1294 tANI_U8 *pDest,
1295 tANI_U32 cur_len,
1296 tANI_U32 rem_len
1297)
1298{
1299 tHddBatchScanRsp *pHead;
1300 tHddBatchScanRsp *pPrev;
1301 tANI_U32 len;
1302
1303 pAdapter->prev_batch_id = 0;
1304 pAdapter->isTruncated = FALSE;
1305
1306 /*head of hdd batch scan response queue*/
1307 pHead = pAdapter->pBatchScanRsp;
1308 while (pHead)
1309 {
1310 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1311 pAdapter);
1312 pDest += len;
1313 cur_len += len;
1314 if(TRUE == pAdapter->isTruncated)
1315 {
1316 /*result is truncated return rest of scan rsp in next req*/
1317 cur_len = rem_len;
1318 break;
1319 }
1320 pPrev = pHead;
1321 pHead = pHead->pNext;
1322 pAdapter->pBatchScanRsp = pHead;
1323 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1324 vos_mem_free(pPrev);
1325 }
1326
1327 return cur_len;
1328}/*End of hdd_populate_user_batch_scan_rsp*/
1329
1330/**---------------------------------------------------------------------------
1331
1332 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1333 scan response data from HDD queue to user space
1334 It does following in detail:
1335 a) if HDD has enough data in its queue then it 1st copies data to user
1336 space and then send get batch scan indication message to FW. In this
1337 case it does not wait on any event and batch scan response data will
1338 be populated in HDD response queue in MC thread context after receiving
1339 indication from FW
1340 b) else send get batch scan indication message to FW and wait on an event
1341 which will be set once HDD receives complete batch scan response from
1342 FW and then this function returns batch scan response to user space
1343
1344 \param - pAdapter Pointer to HDD adapter
1345 \param - pPrivData Pointer to priv_data
1346
1347 \return - 0 for success -EFAULT for failure
1348
1349 --------------------------------------------------------------------------*/
1350
1351int hdd_return_batch_scan_rsp_to_user
1352(
1353 hdd_adapter_t* pAdapter,
1354 hdd_priv_data_t *pPrivData,
1355 tANI_U8 *command
1356)
1357{
1358 tANI_U8 *pDest;
1359 tANI_U32 count = 0;
1360 tANI_U32 len = 0;
1361 tANI_U32 cur_len = 0;
1362 tANI_U32 rem_len = 0;
1363 eHalStatus halStatus;
1364 unsigned long rc;
1365 tSirTriggerBatchScanResultInd *pReq;
1366
1367 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1368 pReq->param = 0;/*batch scan client*/
1369 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1370 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1371
1372 cur_len = pPrivData->used_len;
1373 if (pPrivData->total_len > pPrivData->used_len)
1374 {
1375 rem_len = pPrivData->total_len - pPrivData->used_len;
1376 }
1377 else
1378 {
1379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1380 "%s: Invalid user data buffer total_len %d used_len %d",
1381 __func__, pPrivData->total_len, pPrivData->used_len);
1382 return -EFAULT;
1383 }
1384
1385 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1386 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1387 cur_len, rem_len);
1388 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1389
1390 /*enough scan result available in cache to return to user space or
1391 scan result needs to be fetched 1st from fw and then return*/
1392 if (len < rem_len)
1393 {
1394 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1395 halStatus = sme_TriggerBatchScanResultInd(
1396 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1397 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1398 pAdapter);
1399 if ( eHAL_STATUS_SUCCESS == halStatus )
1400 {
1401 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1402 {
1403 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1404 rc = wait_for_completion_timeout(
1405 &pAdapter->hdd_get_batch_scan_req_var,
1406 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1407 if (0 == rc)
1408 {
1409 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1410 "%s: Timeout waiting to fetch batch scan rsp from fw",
1411 __func__);
1412 return -EFAULT;
1413 }
1414 }
1415
1416 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
1417 "scancount=%ld\n", pAdapter->numScanList);
1418 pDest += len;
1419 cur_len += len;
1420
1421 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1422 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1423 cur_len, rem_len);
1424 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1425
1426 count = 0;
1427 len = (len - pPrivData->used_len);
1428 pDest = (command + pPrivData->used_len);
1429 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1430 "BATCH SCAN RESULT:");
1431 while(count < len)
1432 {
1433 printk("%c", *(pDest + count));
1434 count++;
1435 }
1436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1437 "%s: copy %d data to user buffer", __func__, len);
1438 if (copy_to_user(pPrivData->buf, pDest, len))
1439 {
1440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1441 "%s: failed to copy data to user buffer", __func__);
1442 return -EFAULT;
1443 }
1444 }
1445 else
1446 {
1447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1448 "sme_GetBatchScanScan returned failure halStatus %d",
1449 halStatus);
1450 return -EINVAL;
1451 }
1452 }
1453 else
1454 {
1455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1456 "%s: copy %d data to user buffer", __func__, len);
1457 count = 0;
1458 len = (len - pPrivData->used_len);
1459 pDest = (command + pPrivData->used_len);
1460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1461 "BATCH SCAN RESULT:");
1462 while(count < len)
1463 {
1464 printk("%c", *(pDest + count));
1465 count++;
1466 }
1467 if (copy_to_user(pPrivData->buf, pDest, len))
1468 {
1469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1470 "%s: failed to copy data to user buffer", __func__);
1471 return -EFAULT;
1472 }
1473 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1474 halStatus = sme_TriggerBatchScanResultInd(
1475 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1476 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1477 pAdapter);
1478 if ( eHAL_STATUS_SUCCESS != halStatus )
1479 {
1480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1481 "sme_GetBatchScanScan returned failure halStatus %d",
1482 halStatus);
1483 }
1484 }
1485
1486 return 0;
1487} /*End of hdd_return_batch_scan_rsp_to_user*/
1488
1489#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1490
Jeff Johnson295189b2012-06-20 16:38:30 -07001491int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1492{
1493 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1494 hdd_priv_data_t priv_data;
1495 tANI_U8 *command = NULL;
1496 int ret = 0;
1497
1498 if (NULL == pAdapter)
1499 {
1500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001501 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001502 ret = -ENODEV;
1503 goto exit;
1504 }
1505
Jeff Johnsone7245742012-09-05 17:12:55 -07001506 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001507 {
1508 ret = -EINVAL;
1509 goto exit;
1510 }
1511
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001512 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1513 {
1514 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1515 "%s:LOGP in Progress. Ignore!!!", __func__);
1516 ret = -EBUSY;
1517 goto exit;
1518 }
1519
Jeff Johnson295189b2012-06-20 16:38:30 -07001520 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1521 {
1522 ret = -EFAULT;
1523 goto exit;
1524 }
1525
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001526 if (priv_data.total_len <= 0)
1527 {
1528 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1529 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1530 priv_data.total_len);
1531 ret = -EINVAL;
1532 goto exit;
1533 }
1534
1535 /* Allocate +1 for '\0' */
1536 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001537 if (!command)
1538 {
1539 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001540 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001541 ret = -ENOMEM;
1542 goto exit;
1543 }
1544
1545 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1546 {
1547 ret = -EFAULT;
1548 goto exit;
1549 }
1550
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001551 /* Making sure the command is NUL-terminated */
1552 command[priv_data.total_len] = '\0';
1553
Jeff Johnson295189b2012-06-20 16:38:30 -07001554 if ((SIOCDEVPRIVATE + 1) == cmd)
1555 {
1556 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1557
1558 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001559 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001560
1561 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1562 {
1563 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1564 sizeof(tSirMacAddr)))
1565 {
1566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001567 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001568 ret = -EFAULT;
1569 }
1570 }
Amar Singhal0974e402013-02-12 14:27:46 -08001571 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001572 {
Amar Singhal0974e402013-02-12 14:27:46 -08001573 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001574 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001575
Jeff Johnson295189b2012-06-20 16:38:30 -07001576 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001577
1578 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001579 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001580 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001581 "%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 -07001582 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001583 ret = hdd_setBand_helper(dev, ptr);
1584 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001585 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1586 {
1587 char *country_code;
1588
1589 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001590
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001591 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001592 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301593 hdd_checkandupdate_phymode(pAdapter, country_code);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001594 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1595 (void *)(tSmeChangeCountryCallback)
1596 wlan_hdd_change_country_code_callback,
1597 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1598 if (eHAL_STATUS_SUCCESS == ret)
1599 {
1600 ret = wait_for_completion_interruptible_timeout(
1601 &pAdapter->change_country_code,
1602 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1603 if (0 >= ret)
1604 {
1605 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1606 __func__);
1607 }
1608 }
1609 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001610 {
1611 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001612 "%s: SME Change Country code fail ret=%d", __func__, ret);
1613 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001614 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001615
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001616 }
1617 /*
1618 command should be a string having format
1619 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1620 */
Amar Singhal0974e402013-02-12 14:27:46 -08001621 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001622 {
Amar Singhal0974e402013-02-12 14:27:46 -08001623 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001624
1625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001626 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001627
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001628 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001629 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001630 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1631 {
1632 int suspend = 0;
1633 tANI_U8 *ptr = (tANI_U8*)command + 15;
1634
1635 suspend = *ptr - '0';
1636 hdd_set_wlan_suspend_mode(suspend);
1637 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001638#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1639 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1640 {
1641 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001642 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001643 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1644 eHalStatus status = eHAL_STATUS_SUCCESS;
1645
1646 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1647 value = value + 15;
1648
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001649 /* Convert the value from ascii to integer */
1650 ret = kstrtos8(value, 10, &rssi);
1651 if (ret < 0)
1652 {
1653 /* If the input value is greater than max value of datatype, then also
1654 kstrtou8 fails */
1655 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1656 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
1657 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1658 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1659 ret = -EINVAL;
1660 goto exit;
1661 }
1662
Srinivas Girigowdade697412013-02-14 16:31:48 -08001663 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001664
Srinivas Girigowdade697412013-02-14 16:31:48 -08001665 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1666 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1667 {
1668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1669 "Neighbor lookup threshold value %d is out of range"
1670 " (Min: %d Max: %d)", lookUpThreshold,
1671 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1672 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1673 ret = -EINVAL;
1674 goto exit;
1675 }
1676
1677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1678 "%s: Received Command to Set Roam trigger"
1679 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1680
1681 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1682 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1683 if (eHAL_STATUS_SUCCESS != status)
1684 {
1685 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1686 "%s: Failed to set roam trigger, try again", __func__);
1687 ret = -EPERM;
1688 goto exit;
1689 }
1690
1691 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1692 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1693 }
1694 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1695 {
1696 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1697 int rssi = (-1) * lookUpThreshold;
1698 char extra[32];
1699 tANI_U8 len = 0;
1700
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001701 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001702 if (copy_to_user(priv_data.buf, &extra, len + 1))
1703 {
1704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1705 "%s: failed to copy data to user buffer", __func__);
1706 ret = -EFAULT;
1707 goto exit;
1708 }
1709 }
1710 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1711 {
1712 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001713 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001714 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001715
Srinivas Girigowdade697412013-02-14 16:31:48 -08001716 /* input refresh period is in terms of seconds */
1717 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1718 value = value + 18;
1719 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001720 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001721 if (ret < 0)
1722 {
1723 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001724 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001726 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001727 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001728 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1729 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001730 ret = -EINVAL;
1731 goto exit;
1732 }
1733
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001734 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1735 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001736 {
1737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001738 "Roam scan period value %d is out of range"
1739 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001740 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1741 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001742 ret = -EINVAL;
1743 goto exit;
1744 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001745 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001746
1747 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1748 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001749 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001750
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001751 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1752 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001753 }
1754 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1755 {
1756 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1757 char extra[32];
1758 tANI_U8 len = 0;
1759
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001760 len = scnprintf(extra, sizeof(extra), "%s %d",
1761 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001762 /* Returned value is in units of seconds */
1763 if (copy_to_user(priv_data.buf, &extra, len + 1))
1764 {
1765 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1766 "%s: failed to copy data to user buffer", __func__);
1767 ret = -EFAULT;
1768 goto exit;
1769 }
1770 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001771 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1772 {
1773 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001774 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001775 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001776
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001777 /* input refresh period is in terms of seconds */
1778 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1779 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001780
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001781 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001782 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001783 if (ret < 0)
1784 {
1785 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001786 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001788 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001789 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001790 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1791 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1792 ret = -EINVAL;
1793 goto exit;
1794 }
1795
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001796 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1797 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1798 {
1799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1800 "Neighbor scan results refresh period value %d is out of range"
1801 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1802 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1803 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1804 ret = -EINVAL;
1805 goto exit;
1806 }
1807 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1808
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1810 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001811 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001812
1813 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1814 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1815 }
1816 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1817 {
1818 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1819 char extra[32];
1820 tANI_U8 len = 0;
1821
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001822 len = scnprintf(extra, sizeof(extra), "%s %d",
1823 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001824 /* Returned value is in units of seconds */
1825 if (copy_to_user(priv_data.buf, &extra, len + 1))
1826 {
1827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1828 "%s: failed to copy data to user buffer", __func__);
1829 ret = -EFAULT;
1830 goto exit;
1831 }
1832 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001833#ifdef FEATURE_WLAN_LFR
1834 /* SETROAMMODE */
1835 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1836 {
1837 tANI_U8 *value = command;
1838 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1839
1840 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1841 value = value + SIZE_OF_SETROAMMODE + 1;
1842
1843 /* Convert the value from ascii to integer */
1844 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1845 if (ret < 0)
1846 {
1847 /* If the input value is greater than max value of datatype, then also
1848 kstrtou8 fails */
1849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1850 "%s: kstrtou8 failed range [%d - %d]", __func__,
1851 CFG_LFR_FEATURE_ENABLED_MIN,
1852 CFG_LFR_FEATURE_ENABLED_MAX);
1853 ret = -EINVAL;
1854 goto exit;
1855 }
1856 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1857 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1858 {
1859 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1860 "Roam Mode value %d is out of range"
1861 " (Min: %d Max: %d)", roamMode,
1862 CFG_LFR_FEATURE_ENABLED_MIN,
1863 CFG_LFR_FEATURE_ENABLED_MAX);
1864 ret = -EINVAL;
1865 goto exit;
1866 }
1867
1868 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1869 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
1870 /*
1871 * Note that
1872 * SETROAMMODE 0 is to enable LFR while
1873 * SETROAMMODE 1 is to disable LFR, but
1874 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
1875 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
1876 */
1877 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1878 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
1879 else
1880 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
1881
1882 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
1883 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
1884 }
1885 /* GETROAMMODE */
1886 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
1887 {
1888 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1889 char extra[32];
1890 tANI_U8 len = 0;
1891
1892 /*
1893 * roamMode value shall be inverted because the sementics is different.
1894 */
1895 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1896 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
1897 else
1898 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
1899
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001900 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001901 if (copy_to_user(priv_data.buf, &extra, len + 1))
1902 {
1903 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1904 "%s: failed to copy data to user buffer", __func__);
1905 ret = -EFAULT;
1906 goto exit;
1907 }
1908 }
1909#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08001910#endif
1911#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1912 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1913 {
1914 tANI_U8 *value = command;
1915 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1916
1917 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1918 value = value + 13;
1919 /* Convert the value from ascii to integer */
1920 ret = kstrtou8(value, 10, &roamRssiDiff);
1921 if (ret < 0)
1922 {
1923 /* If the input value is greater than max value of datatype, then also
1924 kstrtou8 fails */
1925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1926 "%s: kstrtou8 failed range [%d - %d]", __func__,
1927 CFG_ROAM_RSSI_DIFF_MIN,
1928 CFG_ROAM_RSSI_DIFF_MAX);
1929 ret = -EINVAL;
1930 goto exit;
1931 }
1932
1933 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1934 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1935 {
1936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1937 "Roam rssi diff value %d is out of range"
1938 " (Min: %d Max: %d)", roamRssiDiff,
1939 CFG_ROAM_RSSI_DIFF_MIN,
1940 CFG_ROAM_RSSI_DIFF_MAX);
1941 ret = -EINVAL;
1942 goto exit;
1943 }
1944
1945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1946 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1947
1948 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1949 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1950 }
1951 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1952 {
1953 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1954 char extra[32];
1955 tANI_U8 len = 0;
1956
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001957 len = scnprintf(extra, sizeof(extra), "%s %d",
1958 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001959 if (copy_to_user(priv_data.buf, &extra, len + 1))
1960 {
1961 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1962 "%s: failed to copy data to user buffer", __func__);
1963 ret = -EFAULT;
1964 goto exit;
1965 }
1966 }
1967#endif
1968#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1969 else if (strncmp(command, "GETBAND", 7) == 0)
1970 {
1971 int band = -1;
1972 char extra[32];
1973 tANI_U8 len = 0;
1974 hdd_getBand_helper(pHddCtx, &band);
1975
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001976 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001977 if (copy_to_user(priv_data.buf, &extra, len + 1))
1978 {
1979 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1980 "%s: failed to copy data to user buffer", __func__);
1981 ret = -EFAULT;
1982 goto exit;
1983 }
1984 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001985 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1986 {
1987 tANI_U8 *value = command;
1988 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1989 tANI_U8 numChannels = 0;
1990 eHalStatus status = eHAL_STATUS_SUCCESS;
1991
1992 status = hdd_parse_channellist(value, ChannelList, &numChannels);
1993 if (eHAL_STATUS_SUCCESS != status)
1994 {
1995 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1996 "%s: Failed to parse channel list information", __func__);
1997 ret = -EINVAL;
1998 goto exit;
1999 }
2000
2001 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2002 {
2003 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2004 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2005 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2006 ret = -EINVAL;
2007 goto exit;
2008 }
2009 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2010 numChannels);
2011 if (eHAL_STATUS_SUCCESS != status)
2012 {
2013 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2014 "%s: Failed to update channel list information", __func__);
2015 ret = -EINVAL;
2016 goto exit;
2017 }
2018 }
2019 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2020 {
2021 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2022 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002023 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002024 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002025 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002026
2027 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2028 ChannelList, &numChannels ))
2029 {
2030 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2031 "%s: failed to get roam scan channel list", __func__);
2032 ret = -EFAULT;
2033 goto exit;
2034 }
2035 /* output channel list is of the format
2036 [Number of roam scan channels][Channel1][Channel2]... */
2037 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002038 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002039 for (j = 0; (j < numChannels); j++)
2040 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002041 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2042 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002043 }
2044
2045 if (copy_to_user(priv_data.buf, &extra, len + 1))
2046 {
2047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2048 "%s: failed to copy data to user buffer", __func__);
2049 ret = -EFAULT;
2050 goto exit;
2051 }
2052 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002053 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2054 {
2055 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2056 char extra[32];
2057 tANI_U8 len = 0;
2058
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002059 /* Check if the features OKC/CCX/11R are supported simultaneously,
2060 then this operation is not permitted (return FAILURE) */
2061 if (ccxMode &&
2062 hdd_is_okc_mode_enabled(pHddCtx) &&
2063 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2064 {
2065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2066 "%s: OKC/CCX/11R are supported simultaneously"
2067 " hence this operation is not permitted!", __func__);
2068 ret = -EPERM;
2069 goto exit;
2070 }
2071
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002072 len = scnprintf(extra, sizeof(extra), "%s %d",
2073 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002074 if (copy_to_user(priv_data.buf, &extra, len + 1))
2075 {
2076 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2077 "%s: failed to copy data to user buffer", __func__);
2078 ret = -EFAULT;
2079 goto exit;
2080 }
2081 }
2082 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2083 {
2084 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2085 char extra[32];
2086 tANI_U8 len = 0;
2087
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002088 /* Check if the features OKC/CCX/11R are supported simultaneously,
2089 then this operation is not permitted (return FAILURE) */
2090 if (okcMode &&
2091 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2092 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2093 {
2094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2095 "%s: OKC/CCX/11R are supported simultaneously"
2096 " hence this operation is not permitted!", __func__);
2097 ret = -EPERM;
2098 goto exit;
2099 }
2100
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002101 len = scnprintf(extra, sizeof(extra), "%s %d",
2102 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002103 if (copy_to_user(priv_data.buf, &extra, len + 1))
2104 {
2105 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2106 "%s: failed to copy data to user buffer", __func__);
2107 ret = -EFAULT;
2108 goto exit;
2109 }
2110 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002111 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002112 {
2113 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2114 char extra[32];
2115 tANI_U8 len = 0;
2116
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002117 len = scnprintf(extra, sizeof(extra), "%s %d",
2118 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002119 if (copy_to_user(priv_data.buf, &extra, len + 1))
2120 {
2121 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2122 "%s: failed to copy data to user buffer", __func__);
2123 ret = -EFAULT;
2124 goto exit;
2125 }
2126 }
2127 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2128 {
2129 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2130 char extra[32];
2131 tANI_U8 len = 0;
2132
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002133 len = scnprintf(extra, sizeof(extra), "%s %d",
2134 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002135 if (copy_to_user(priv_data.buf, &extra, len + 1))
2136 {
2137 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2138 "%s: failed to copy data to user buffer", __func__);
2139 ret = -EFAULT;
2140 goto exit;
2141 }
2142 }
2143 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2144 {
2145 tANI_U8 *value = command;
2146 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2147
2148 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2149 value = value + 26;
2150 /* Convert the value from ascii to integer */
2151 ret = kstrtou8(value, 10, &minTime);
2152 if (ret < 0)
2153 {
2154 /* If the input value is greater than max value of datatype, then also
2155 kstrtou8 fails */
2156 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2157 "%s: kstrtou8 failed range [%d - %d]", __func__,
2158 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2159 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2160 ret = -EINVAL;
2161 goto exit;
2162 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002163 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2164 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2165 {
2166 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2167 "scan min channel time value %d is out of range"
2168 " (Min: %d Max: %d)", minTime,
2169 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2170 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2171 ret = -EINVAL;
2172 goto exit;
2173 }
2174
2175 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2176 "%s: Received Command to change channel min time = %d", __func__, minTime);
2177
2178 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2179 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2180 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002181 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2182 {
2183 tANI_U8 *value = command;
2184 tANI_U8 channel = 0;
2185 tANI_U8 dwellTime = 0;
2186 tANI_U8 bufLen = 0;
2187 tANI_U8 *buf = NULL;
2188 tSirMacAddr targetApBssid;
2189 eHalStatus status = eHAL_STATUS_SUCCESS;
2190 struct ieee80211_channel chan;
2191 tANI_U8 finalLen = 0;
2192 tANI_U8 *finalBuf = NULL;
2193 tANI_U8 temp = 0;
2194 u64 cookie;
2195 hdd_station_ctx_t *pHddStaCtx = NULL;
2196 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2197
2198 /* if not associated, no need to send action frame */
2199 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2200 {
2201 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2202 ret = -EINVAL;
2203 goto exit;
2204 }
2205
2206 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2207 &dwellTime, &buf, &bufLen);
2208 if (eHAL_STATUS_SUCCESS != status)
2209 {
2210 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2211 "%s: Failed to parse send action frame data", __func__);
2212 ret = -EINVAL;
2213 goto exit;
2214 }
2215
2216 /* if the target bssid is different from currently associated AP,
2217 then no need to send action frame */
2218 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2219 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2220 {
2221 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2222 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002223 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002224 goto exit;
2225 }
2226
2227 /* if the channel number is different from operating channel then
2228 no need to send action frame */
2229 if (channel != pHddStaCtx->conn_info.operationChannel)
2230 {
2231 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2232 "%s: channel(%d) is different from operating channel(%d)",
2233 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2234 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002235 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002236 goto exit;
2237 }
2238 chan.center_freq = sme_ChnToFreq(channel);
2239
2240 finalLen = bufLen + 24;
2241 finalBuf = vos_mem_malloc(finalLen);
2242 if (NULL == finalBuf)
2243 {
2244 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2245 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002246 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002247 goto exit;
2248 }
2249 vos_mem_zero(finalBuf, finalLen);
2250
2251 /* Fill subtype */
2252 temp = SIR_MAC_MGMT_ACTION << 4;
2253 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2254
2255 /* Fill type */
2256 temp = SIR_MAC_MGMT_FRAME;
2257 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2258
2259 /* Fill destination address (bssid of the AP) */
2260 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2261
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002262 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002263 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2264
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002265 /* Fill BSSID (AP mac address) */
2266 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002267
2268 /* Fill received buffer from 24th address */
2269 vos_mem_copy(finalBuf + 24, buf, bufLen);
2270
Jeff Johnson11c33152013-04-16 17:52:40 -07002271 /* done with the parsed buffer */
2272 vos_mem_free(buf);
2273
Yue Maf49ba872013-08-19 12:04:25 -07002274 wlan_hdd_action( NULL,
2275#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2276 &(pAdapter->wdev),
2277#else
2278 dev,
2279#endif
2280 &chan, 0,
2281#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2282 NL80211_CHAN_HT20, 1,
2283#endif
2284 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002285 1, &cookie );
2286 vos_mem_free(finalBuf);
2287 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002288 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2289 {
2290 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2291 char extra[32];
2292 tANI_U8 len = 0;
2293
2294 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002295 len = scnprintf(extra, sizeof(extra), "%s %d",
2296 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002297 if (copy_to_user(priv_data.buf, &extra, len + 1))
2298 {
2299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2300 "%s: failed to copy data to user buffer", __func__);
2301 ret = -EFAULT;
2302 goto exit;
2303 }
2304 }
2305 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2306 {
2307 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002308 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002309 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002310
2311 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2312 value = value + 19;
2313 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002314 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002315 if (ret < 0)
2316 {
2317 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002318 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002320 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002321 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2322 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2323 ret = -EINVAL;
2324 goto exit;
2325 }
2326
2327 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2328 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2329 {
2330 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2331 "lfr mode value %d is out of range"
2332 " (Min: %d Max: %d)", maxTime,
2333 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2334 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2335 ret = -EINVAL;
2336 goto exit;
2337 }
2338
2339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2340 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2341
2342 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002343
2344 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2345 * where RFS is the RF Switching time. It is twice RFS to consider the
2346 * time to go off channel and return to the home channel. */
2347 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2348 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2349 {
2350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2351 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
2352 " Hence enforcing home away time to disable (0)",
2353 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2354 homeAwayTime = 0;
2355 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2356 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2357 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002358 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2359 }
2360 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2361 {
2362 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2363 char extra[32];
2364 tANI_U8 len = 0;
2365
2366 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002367 len = scnprintf(extra, sizeof(extra), "%s %d",
2368 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002369 if (copy_to_user(priv_data.buf, &extra, len + 1))
2370 {
2371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2372 "%s: failed to copy data to user buffer", __func__);
2373 ret = -EFAULT;
2374 goto exit;
2375 }
2376 }
2377 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2378 {
2379 tANI_U8 *value = command;
2380 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2381
2382 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2383 value = value + 16;
2384 /* Convert the value from ascii to integer */
2385 ret = kstrtou16(value, 10, &val);
2386 if (ret < 0)
2387 {
2388 /* If the input value is greater than max value of datatype, then also
2389 kstrtou16 fails */
2390 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2391 "%s: kstrtou16 failed range [%d - %d]", __func__,
2392 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2393 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2394 ret = -EINVAL;
2395 goto exit;
2396 }
2397
2398 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2399 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2400 {
2401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2402 "scan home time value %d is out of range"
2403 " (Min: %d Max: %d)", val,
2404 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2405 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2406 ret = -EINVAL;
2407 goto exit;
2408 }
2409
2410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2411 "%s: Received Command to change scan home time = %d", __func__, val);
2412
2413 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2414 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2415 }
2416 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2417 {
2418 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2419 char extra[32];
2420 tANI_U8 len = 0;
2421
2422 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002423 len = scnprintf(extra, sizeof(extra), "%s %d",
2424 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002425 if (copy_to_user(priv_data.buf, &extra, len + 1))
2426 {
2427 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2428 "%s: failed to copy data to user buffer", __func__);
2429 ret = -EFAULT;
2430 goto exit;
2431 }
2432 }
2433 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2434 {
2435 tANI_U8 *value = command;
2436 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2437
2438 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2439 value = value + 17;
2440 /* Convert the value from ascii to integer */
2441 ret = kstrtou8(value, 10, &val);
2442 if (ret < 0)
2443 {
2444 /* If the input value is greater than max value of datatype, then also
2445 kstrtou8 fails */
2446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2447 "%s: kstrtou8 failed range [%d - %d]", __func__,
2448 CFG_ROAM_INTRA_BAND_MIN,
2449 CFG_ROAM_INTRA_BAND_MAX);
2450 ret = -EINVAL;
2451 goto exit;
2452 }
2453
2454 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2455 (val > CFG_ROAM_INTRA_BAND_MAX))
2456 {
2457 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2458 "intra band mode value %d is out of range"
2459 " (Min: %d Max: %d)", val,
2460 CFG_ROAM_INTRA_BAND_MIN,
2461 CFG_ROAM_INTRA_BAND_MAX);
2462 ret = -EINVAL;
2463 goto exit;
2464 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002465 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2466 "%s: Received Command to change intra band = %d", __func__, val);
2467
2468 pHddCtx->cfg_ini->nRoamIntraBand = val;
2469 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2470 }
2471 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2472 {
2473 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2474 char extra[32];
2475 tANI_U8 len = 0;
2476
2477 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002478 len = scnprintf(extra, sizeof(extra), "%s %d",
2479 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002480 if (copy_to_user(priv_data.buf, &extra, len + 1))
2481 {
2482 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2483 "%s: failed to copy data to user buffer", __func__);
2484 ret = -EFAULT;
2485 goto exit;
2486 }
2487 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002488 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2489 {
2490 tANI_U8 *value = command;
2491 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2492
2493 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2494 value = value + 15;
2495 /* Convert the value from ascii to integer */
2496 ret = kstrtou8(value, 10, &nProbes);
2497 if (ret < 0)
2498 {
2499 /* If the input value is greater than max value of datatype, then also
2500 kstrtou8 fails */
2501 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2502 "%s: kstrtou8 failed range [%d - %d]", __func__,
2503 CFG_ROAM_SCAN_N_PROBES_MIN,
2504 CFG_ROAM_SCAN_N_PROBES_MAX);
2505 ret = -EINVAL;
2506 goto exit;
2507 }
2508
2509 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2510 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2511 {
2512 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2513 "NProbes value %d is out of range"
2514 " (Min: %d Max: %d)", nProbes,
2515 CFG_ROAM_SCAN_N_PROBES_MIN,
2516 CFG_ROAM_SCAN_N_PROBES_MAX);
2517 ret = -EINVAL;
2518 goto exit;
2519 }
2520
2521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2522 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2523
2524 pHddCtx->cfg_ini->nProbes = nProbes;
2525 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2526 }
2527 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2528 {
2529 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2530 char extra[32];
2531 tANI_U8 len = 0;
2532
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002533 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002534 if (copy_to_user(priv_data.buf, &extra, len + 1))
2535 {
2536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2537 "%s: failed to copy data to user buffer", __func__);
2538 ret = -EFAULT;
2539 goto exit;
2540 }
2541 }
2542 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2543 {
2544 tANI_U8 *value = command;
2545 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002546 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002547
2548 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2549 /* input value is in units of msec */
2550 value = value + 20;
2551 /* Convert the value from ascii to integer */
2552 ret = kstrtou16(value, 10, &homeAwayTime);
2553 if (ret < 0)
2554 {
2555 /* If the input value is greater than max value of datatype, then also
2556 kstrtou8 fails */
2557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2558 "%s: kstrtou8 failed range [%d - %d]", __func__,
2559 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2560 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2561 ret = -EINVAL;
2562 goto exit;
2563 }
2564
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002565 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2566 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2567 {
2568 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2569 "homeAwayTime value %d is out of range"
2570 " (Min: %d Max: %d)", homeAwayTime,
2571 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2572 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2573 ret = -EINVAL;
2574 goto exit;
2575 }
2576
2577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2578 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2579
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002580 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2581 * where RFS is the RF Switching time. It is twice RFS to consider the
2582 * time to go off channel and return to the home channel. */
2583 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2584 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2585 {
2586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2587 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
2588 " Hence enforcing home away time to disable (0)",
2589 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2590 homeAwayTime = 0;
2591 }
2592
2593 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2594 {
2595 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2596 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2597 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002598 }
2599 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2600 {
2601 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2602 char extra[32];
2603 tANI_U8 len = 0;
2604
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002605 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002606 if (copy_to_user(priv_data.buf, &extra, len + 1))
2607 {
2608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2609 "%s: failed to copy data to user buffer", __func__);
2610 ret = -EFAULT;
2611 goto exit;
2612 }
2613 }
2614 else if (strncmp(command, "REASSOC", 7) == 0)
2615 {
2616 tANI_U8 *value = command;
2617 tANI_U8 channel = 0;
2618 tSirMacAddr targetApBssid;
2619 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002620#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2621 tCsrHandoffRequest handoffInfo;
2622#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002623 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002624 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2625
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002626 /* if not associated, no need to proceed with reassoc */
2627 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2628 {
2629 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2630 ret = -EINVAL;
2631 goto exit;
2632 }
2633
2634 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2635 if (eHAL_STATUS_SUCCESS != status)
2636 {
2637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2638 "%s: Failed to parse reassoc command data", __func__);
2639 ret = -EINVAL;
2640 goto exit;
2641 }
2642
2643 /* if the target bssid is same as currently associated AP,
2644 then no need to proceed with reassoc */
2645 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2646 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2647 {
2648 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2649 ret = -EINVAL;
2650 goto exit;
2651 }
2652
2653 /* Check channel number is a valid channel number */
2654 if(VOS_STATUS_SUCCESS !=
2655 wlan_hdd_validate_operation_channel(pAdapter, channel))
2656 {
2657 hddLog(VOS_TRACE_LEVEL_ERROR,
2658 "%s: Invalid Channel [%d] \n", __func__, channel);
2659 return -EINVAL;
2660 }
2661
2662 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002663#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2664 handoffInfo.channel = channel;
2665 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2666 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2667#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002668 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002669#endif
2670#ifdef FEATURE_WLAN_LFR
2671 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2672 {
2673 tANI_U8 *value = command;
2674 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2675
2676 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2677 value = value + 12;
2678 /* Convert the value from ascii to integer */
2679 ret = kstrtou8(value, 10, &lfrMode);
2680 if (ret < 0)
2681 {
2682 /* If the input value is greater than max value of datatype, then also
2683 kstrtou8 fails */
2684 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2685 "%s: kstrtou8 failed range [%d - %d]", __func__,
2686 CFG_LFR_FEATURE_ENABLED_MIN,
2687 CFG_LFR_FEATURE_ENABLED_MAX);
2688 ret = -EINVAL;
2689 goto exit;
2690 }
2691
2692 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2693 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2694 {
2695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2696 "lfr mode value %d is out of range"
2697 " (Min: %d Max: %d)", lfrMode,
2698 CFG_LFR_FEATURE_ENABLED_MIN,
2699 CFG_LFR_FEATURE_ENABLED_MAX);
2700 ret = -EINVAL;
2701 goto exit;
2702 }
2703
2704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2705 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2706
2707 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2708 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2709 }
2710#endif
2711#ifdef WLAN_FEATURE_VOWIFI_11R
2712 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2713 {
2714 tANI_U8 *value = command;
2715 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2716
2717 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2718 value = value + 18;
2719 /* Convert the value from ascii to integer */
2720 ret = kstrtou8(value, 10, &ft);
2721 if (ret < 0)
2722 {
2723 /* If the input value is greater than max value of datatype, then also
2724 kstrtou8 fails */
2725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2726 "%s: kstrtou8 failed range [%d - %d]", __func__,
2727 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2728 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2729 ret = -EINVAL;
2730 goto exit;
2731 }
2732
2733 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2734 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2735 {
2736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2737 "ft mode value %d is out of range"
2738 " (Min: %d Max: %d)", ft,
2739 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2740 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2741 ret = -EINVAL;
2742 goto exit;
2743 }
2744
2745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2746 "%s: Received Command to change ft mode = %d", __func__, ft);
2747
2748 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2749 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2750 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302751
2752 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2753 {
2754 tANI_U8 *value = command;
2755 tSirMacAddr targetApBssid;
2756 tANI_U8 trigger = 0;
2757 eHalStatus status = eHAL_STATUS_SUCCESS;
2758 hdd_station_ctx_t *pHddStaCtx = NULL;
2759 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2760
2761 /* if not associated, no need to proceed with reassoc */
2762 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2763 {
2764 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2765 ret = -EINVAL;
2766 goto exit;
2767 }
2768
2769 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2770 if (eHAL_STATUS_SUCCESS != status)
2771 {
2772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2773 "%s: Failed to parse reassoc command data", __func__);
2774 ret = -EINVAL;
2775 goto exit;
2776 }
2777
2778 /* if the target bssid is same as currently associated AP,
2779 then no need to proceed with reassoc */
2780 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2781 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2782 {
2783 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2784 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2785 __func__);
2786 ret = -EINVAL;
2787 goto exit;
2788 }
2789
2790 /* Proceed with scan/roam */
2791 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2792 &targetApBssid[0],
2793 (tSmeFastRoamTrigger)(trigger));
2794 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002795#endif
2796#ifdef FEATURE_WLAN_CCX
2797 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2798 {
2799 tANI_U8 *value = command;
2800 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2801
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002802 /* Check if the features OKC/CCX/11R are supported simultaneously,
2803 then this operation is not permitted (return FAILURE) */
2804 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2805 hdd_is_okc_mode_enabled(pHddCtx) &&
2806 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2807 {
2808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2809 "%s: OKC/CCX/11R are supported simultaneously"
2810 " hence this operation is not permitted!", __func__);
2811 ret = -EPERM;
2812 goto exit;
2813 }
2814
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002815 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2816 value = value + 11;
2817 /* Convert the value from ascii to integer */
2818 ret = kstrtou8(value, 10, &ccxMode);
2819 if (ret < 0)
2820 {
2821 /* If the input value is greater than max value of datatype, then also
2822 kstrtou8 fails */
2823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2824 "%s: kstrtou8 failed range [%d - %d]", __func__,
2825 CFG_CCX_FEATURE_ENABLED_MIN,
2826 CFG_CCX_FEATURE_ENABLED_MAX);
2827 ret = -EINVAL;
2828 goto exit;
2829 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002830 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2831 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2832 {
2833 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2834 "Ccx mode value %d is out of range"
2835 " (Min: %d Max: %d)", ccxMode,
2836 CFG_CCX_FEATURE_ENABLED_MIN,
2837 CFG_CCX_FEATURE_ENABLED_MAX);
2838 ret = -EINVAL;
2839 goto exit;
2840 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2842 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
2843
2844 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
2845 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
2846 }
2847#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002848 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
2849 {
2850 tANI_U8 *value = command;
2851 tANI_BOOLEAN roamScanControl = 0;
2852
2853 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
2854 value = value + 19;
2855 /* Convert the value from ascii to integer */
2856 ret = kstrtou8(value, 10, &roamScanControl);
2857 if (ret < 0)
2858 {
2859 /* If the input value is greater than max value of datatype, then also
2860 kstrtou8 fails */
2861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2862 "%s: kstrtou8 failed ", __func__);
2863 ret = -EINVAL;
2864 goto exit;
2865 }
2866
2867 if (0 != roamScanControl)
2868 {
2869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2870 "roam scan control invalid value = %d",
2871 roamScanControl);
2872 ret = -EINVAL;
2873 goto exit;
2874 }
2875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2876 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
2877
2878 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
2879 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002880#ifdef FEATURE_WLAN_OKC
2881 else if (strncmp(command, "SETOKCMODE", 10) == 0)
2882 {
2883 tANI_U8 *value = command;
2884 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
2885
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002886 /* Check if the features OKC/CCX/11R are supported simultaneously,
2887 then this operation is not permitted (return FAILURE) */
2888 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2889 hdd_is_okc_mode_enabled(pHddCtx) &&
2890 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2891 {
2892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2893 "%s: OKC/CCX/11R are supported simultaneously"
2894 " hence this operation is not permitted!", __func__);
2895 ret = -EPERM;
2896 goto exit;
2897 }
2898
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002899 /* Move pointer to ahead of SETOKCMODE<delimiter> */
2900 value = value + 11;
2901 /* Convert the value from ascii to integer */
2902 ret = kstrtou8(value, 10, &okcMode);
2903 if (ret < 0)
2904 {
2905 /* If the input value is greater than max value of datatype, then also
2906 kstrtou8 fails */
2907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2908 "%s: kstrtou8 failed range [%d - %d]", __func__,
2909 CFG_OKC_FEATURE_ENABLED_MIN,
2910 CFG_OKC_FEATURE_ENABLED_MAX);
2911 ret = -EINVAL;
2912 goto exit;
2913 }
2914
2915 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
2916 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
2917 {
2918 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2919 "Okc mode value %d is out of range"
2920 " (Min: %d Max: %d)", okcMode,
2921 CFG_OKC_FEATURE_ENABLED_MIN,
2922 CFG_OKC_FEATURE_ENABLED_MAX);
2923 ret = -EINVAL;
2924 goto exit;
2925 }
2926
2927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2928 "%s: Received Command to change okc mode = %d", __func__, okcMode);
2929
2930 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
2931 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002932 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
2933 {
2934 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
2935 char extra[32];
2936 tANI_U8 len = 0;
2937
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002938 len = scnprintf(extra, sizeof(extra), "%s %d",
2939 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002940 if (copy_to_user(priv_data.buf, &extra, len + 1))
2941 {
2942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2943 "%s: failed to copy data to user buffer", __func__);
2944 ret = -EFAULT;
2945 goto exit;
2946 }
2947 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002948#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302949#ifdef WLAN_FEATURE_PACKET_FILTERING
2950 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2951 {
2952 tANI_U8 filterType = 0;
2953 tANI_U8 *value = command;
2954
2955 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2956 value = value + 22;
2957
2958 /* Convert the value from ascii to integer */
2959 ret = kstrtou8(value, 10, &filterType);
2960 if (ret < 0)
2961 {
2962 /* If the input value is greater than max value of datatype,
2963 * then also kstrtou8 fails
2964 */
2965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2966 "%s: kstrtou8 failed range ", __func__);
2967 ret = -EINVAL;
2968 goto exit;
2969 }
2970
2971 if (filterType != 0 && filterType != 1)
2972 {
2973 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2974 "%s: Accepted Values are 0 and 1 ", __func__);
2975 ret = -EINVAL;
2976 goto exit;
2977 }
2978 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2979 pAdapter->sessionId);
2980 }
2981#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302982 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2983 {
2984 char *dhcpPhase;
2985 dhcpPhase = command + 12;
2986 if ('1' == *dhcpPhase)
2987 {
2988 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2989 pAdapter->macAddressCurrent.bytes);
2990 }
2991 else if ('2' == *dhcpPhase)
2992 {
2993 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
2994 pAdapter->macAddressCurrent.bytes);
2995 }
2996 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07002997 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
2998 {
2999 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3000 }
3001 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3002 {
3003 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3004 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303005 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3006 {
3007 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3008 char extra[32];
3009 tANI_U8 len = 0;
3010
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003011 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303012 (int)pCfg->nActiveMaxChnTime);
3013 if (copy_to_user(priv_data.buf, &extra, len + 1))
3014 {
3015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3016 "%s: failed to copy data to user buffer", __func__);
3017 ret = -EFAULT;
3018 goto exit;
3019 }
3020 ret = len;
3021 }
3022 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3023 {
3024 tANI_U8 *value = command;
3025 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3026 int val = 0, temp;
3027
3028 value = value + 13;
3029 temp = kstrtou32(value, 10, &val);
3030 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3031 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3032 {
3033 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3034 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3035 ret = -EFAULT;
3036 goto exit;
3037 }
3038 pCfg->nActiveMaxChnTime = val;
3039 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003040 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3041 {
3042 tANI_U8 filterType = 0;
3043 tANI_U8 *value;
3044 value = command + 9;
3045
3046 /* Convert the value from ascii to integer */
3047 ret = kstrtou8(value, 10, &filterType);
3048 if (ret < 0)
3049 {
3050 /* If the input value is greater than max value of datatype,
3051 * then also kstrtou8 fails
3052 */
3053 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3054 "%s: kstrtou8 failed range ", __func__);
3055 ret = -EINVAL;
3056 goto exit;
3057 }
3058 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3059 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3060 {
3061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3062 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3063 " 2-Sink ", __func__);
3064 ret = -EINVAL;
3065 goto exit;
3066 }
3067 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3068 pHddCtx->drvr_miracast = filterType;
3069 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3070 }
Leo Chang614d2072013-08-22 14:59:44 -07003071 else if (strncmp(command, "SETMCRATE", 9) == 0)
3072 {
3073 int rc;
3074 tANI_U8 *value = command;
3075 int targetRate;
3076
3077 /* Only valid for SAP mode */
3078 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3079 {
3080 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3081 "%s: SAP mode is not running", __func__);
3082 ret = -EFAULT;
3083 goto exit;
3084 }
3085
3086 /* Move pointer to ahead of SETMCRATE<delimiter> */
3087 /* input value is in units of hundred kbps */
3088 value = value + 10;
3089 /* Convert the value from ascii to integer, decimal base */
3090 ret = kstrtouint(value, 10, &targetRate);
3091
3092 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
3093 if (rc)
3094 {
3095 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3096 "%s: Set MC Rate Fail %d", __func__, rc);
3097 ret = -EFAULT;
3098 goto exit;
3099 }
3100 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303101#ifdef FEATURE_WLAN_BATCH_SCAN
3102 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3103 {
3104 char extra[32];
3105 tANI_U8 len = 0;
3106 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3107
3108 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3109 {
3110 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3111 "%s: Batch scan feature is not supported by FW", __func__);
3112 ret = -EINVAL;
3113 goto exit;
3114 }
3115
3116 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3117 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3118 {
3119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3120 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3121 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3122 " mode",
3123 pAdapter->device_mode);
3124 ret = -EINVAL;
3125 goto exit;
3126 }
3127
3128 len = snprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
3129 version);
3130 if (copy_to_user(priv_data.buf, &extra, len + 1))
3131 {
3132 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3133 "%s: failed to copy data to user buffer", __func__);
3134 ret = -EFAULT;
3135 goto exit;
3136 }
3137 ret = HDD_BATCH_SCAN_VERSION;
3138 }
3139 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3140 {
3141 int status;
3142 tANI_U8 *value = (command + 16);
3143 eHalStatus halStatus;
3144 unsigned long rc;
3145 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3146 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3147
3148 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3149 {
3150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3151 "%s: Batch scan feature is not supported by FW", __func__);
3152 ret = -EINVAL;
3153 goto exit;
3154 }
3155
3156 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3157 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3158 {
3159 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3160 "Received WLS_BATCHING_SET command in invalid mode %d "
3161 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3162 pAdapter->device_mode);
3163 ret = -EINVAL;
3164 goto exit;
3165 }
3166
3167 status = hdd_parse_set_batchscan_command(value, pReq);
3168 if (status)
3169 {
3170 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3171 "Invalid WLS_BATCHING_SET command");
3172 ret = -EINVAL;
3173 goto exit;
3174 }
3175 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3176 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3177 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3178 pAdapter);
3179
3180 if ( eHAL_STATUS_SUCCESS == halStatus )
3181 {
3182 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3183 "sme_SetBatchScanReq returned success halStatus %d",
3184 halStatus);
3185 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3186 {
3187 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3188 rc = wait_for_completion_timeout(
3189 &pAdapter->hdd_set_batch_scan_req_var,
3190 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3191 if (0 == rc)
3192 {
3193 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3194 "%s: Timeout waiting for set batch scan to complete",
3195 __func__);
3196 ret = -EINVAL;
3197 goto exit;
3198 }
3199 }
3200 if ( !pRsp->nScansToBatch )
3201 {
3202 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3203 "%s: Received set batch scan failure response from FW",
3204 __func__, pRsp->nScansToBatch);
3205 ret = -EINVAL;
3206 goto exit;
3207 }
3208 /*As per the Batch Scan Framework API we should return the MIN of
3209 either MSCAN or the max # of scans firmware can cache*/
3210 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3211
3212 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3213 "%s: request MSCAN %d response MSCAN %d ret %d",
3214 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3215 }
3216 else
3217 {
3218 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3219 "sme_SetBatchScanReq returned failure halStatus %d",
3220 halStatus);
3221 ret = -EINVAL;
3222 goto exit;
3223 }
3224 }
3225 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3226 {
3227 eHalStatus halStatus;
3228 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3229 pInd->param = 0;
3230
3231 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3232 {
3233 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3234 "%s: Batch scan feature is not supported by FW", __func__);
3235 ret = -EINVAL;
3236 goto exit;
3237 }
3238
3239 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3240 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3241 {
3242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3243 "Received WLS_BATCHING_STOP command in invalid mode %d "
3244 "WLS_BATCHING_STOP is only allowed in infra STA/P2P client"
3245 " mode",
3246 pAdapter->device_mode);
3247 ret = -EINVAL;
3248 goto exit;
3249 }
3250
3251 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3252 pAdapter->sessionId);
3253 if ( eHAL_STATUS_SUCCESS == halStatus )
3254 {
3255 ret = 0;
3256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3257 "sme_StopBatchScanInd returned success halStatus %d",
3258 halStatus);
3259 }
3260 else
3261 {
3262 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3263 "sme_StopBatchScanInd returned failure halStatus %d",
3264 halStatus);
3265 ret = -EINVAL;
3266 goto exit;
3267 }
3268 }
3269 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3270 {
3271 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3272 {
3273 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3274 "%s: Batch scan feature is not supported by FW", __func__);
3275 ret = -EINVAL;
3276 goto exit;
3277 }
3278
3279 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3280 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3281 {
3282 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3283 "Received WLS_BATCHING_GET command in invalid mode %d "
3284 "WLS_BATCHING_GET is only allowed in infra STA/P2P client"
3285 " mode",
3286 pAdapter->device_mode);
3287 ret = -EINVAL;
3288 goto exit;
3289 }
3290
3291 priv_data.used_len = 16;
3292 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3293 }
3294#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003295 else {
3296 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3297 __func__, command);
3298 }
3299
Jeff Johnson295189b2012-06-20 16:38:30 -07003300 }
3301exit:
3302 if (command)
3303 {
3304 kfree(command);
3305 }
3306 return ret;
3307}
3308
Srinivas Girigowdade697412013-02-14 16:31:48 -08003309#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3310void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3311{
3312 eCsrBand band = -1;
3313 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3314 switch (band)
3315 {
3316 case eCSR_BAND_ALL:
3317 *pBand = WLAN_HDD_UI_BAND_AUTO;
3318 break;
3319
3320 case eCSR_BAND_24:
3321 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3322 break;
3323
3324 case eCSR_BAND_5G:
3325 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3326 break;
3327
3328 default:
3329 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3330 *pBand = -1;
3331 break;
3332 }
3333}
3334
3335/**---------------------------------------------------------------------------
3336
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003337 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3338
3339 This function parses the send action frame data passed in the format
3340 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3341
Srinivas Girigowda56076852013-08-20 14:00:50 -07003342 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003343 \param - pTargetApBssid Pointer to target Ap bssid
3344 \param - pChannel Pointer to the Target AP channel
3345 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3346 \param - pBuf Pointer to data
3347 \param - pBufLen Pointer to data length
3348
3349 \return - 0 for success non-zero for failure
3350
3351 --------------------------------------------------------------------------*/
3352VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3353 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3354{
3355 tANI_U8 *inPtr = pValue;
3356 tANI_U8 *dataEnd;
3357 int tempInt;
3358 int j = 0;
3359 int i = 0;
3360 int v = 0;
3361 tANI_U8 tempBuf[32];
3362 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003363 /* 12 hexa decimal digits and 5 ':' */
3364 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003365
3366 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3367 /*no argument after the command*/
3368 if (NULL == inPtr)
3369 {
3370 return -EINVAL;
3371 }
3372
3373 /*no space after the command*/
3374 else if (SPACE_ASCII_VALUE != *inPtr)
3375 {
3376 return -EINVAL;
3377 }
3378
3379 /*removing empty spaces*/
3380 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3381
3382 /*no argument followed by spaces*/
3383 if ('\0' == *inPtr)
3384 {
3385 return -EINVAL;
3386 }
3387
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003388 v = sscanf(inPtr, "%17s", macAddress);
3389 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003390 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003391 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3392 "Invalid MAC address or All hex inputs are not read (%d)", v);
3393 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003394 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003395
3396 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3397 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3398 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3399 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3400 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3401 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003402
3403 /* point to the next argument */
3404 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3405 /*no argument after the command*/
3406 if (NULL == inPtr) return -EINVAL;
3407
3408 /*removing empty spaces*/
3409 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3410
3411 /*no argument followed by spaces*/
3412 if ('\0' == *inPtr)
3413 {
3414 return -EINVAL;
3415 }
3416
3417 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003418 v = sscanf(inPtr, "%32s ", tempBuf);
3419 if (1 != v) return -EINVAL;
3420
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003421 v = kstrtos32(tempBuf, 10, &tempInt);
3422 if ( v < 0) return -EINVAL;
3423
3424 *pChannel = tempInt;
3425
3426 /* point to the next argument */
3427 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3428 /*no argument after the command*/
3429 if (NULL == inPtr) return -EINVAL;
3430 /*removing empty spaces*/
3431 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3432
3433 /*no argument followed by spaces*/
3434 if ('\0' == *inPtr)
3435 {
3436 return -EINVAL;
3437 }
3438
3439 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003440 v = sscanf(inPtr, "%32s ", tempBuf);
3441 if (1 != v) return -EINVAL;
3442
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003443 v = kstrtos32(tempBuf, 10, &tempInt);
3444 if ( v < 0) return -EINVAL;
3445
3446 *pDwellTime = tempInt;
3447
3448 /* point to the next argument */
3449 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3450 /*no argument after the command*/
3451 if (NULL == inPtr) return -EINVAL;
3452 /*removing empty spaces*/
3453 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3454
3455 /*no argument followed by spaces*/
3456 if ('\0' == *inPtr)
3457 {
3458 return -EINVAL;
3459 }
3460
3461 /* find the length of data */
3462 dataEnd = inPtr;
3463 while(('\0' != *dataEnd) )
3464 {
3465 dataEnd++;
3466 ++(*pBufLen);
3467 }
3468 if ( *pBufLen <= 0) return -EINVAL;
3469
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07003470 /* Allocate the number of bytes based on the number of input characters
3471 whether it is even or odd.
3472 if the number of input characters are even, then we need N/2 byte.
3473 if the number of input characters are odd, then we need do (N+1)/2 to
3474 compensate rounding off.
3475 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
3476 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
3477 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003478 if (NULL == *pBuf)
3479 {
3480 hddLog(VOS_TRACE_LEVEL_FATAL,
3481 "%s: vos_mem_alloc failed ", __func__);
3482 return -EINVAL;
3483 }
3484
3485 /* the buffer received from the upper layer is character buffer,
3486 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
3487 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
3488 and f0 in 3rd location */
3489 for (i = 0, j = 0; j < *pBufLen; j += 2)
3490 {
3491 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
3492 (*pBuf)[i++] = tempByte;
3493 }
3494 *pBufLen = i;
3495 return VOS_STATUS_SUCCESS;
3496}
3497
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003498/**---------------------------------------------------------------------------
3499
Srinivas Girigowdade697412013-02-14 16:31:48 -08003500 \brief hdd_parse_channellist() - HDD Parse channel list
3501
3502 This function parses the channel list passed in the format
3503 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003504 if the Number of channels (N) does not match with the actual number of channels passed
3505 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
3506 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
3507 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
3508 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08003509
3510 \param - pValue Pointer to input channel list
3511 \param - ChannelList Pointer to local output array to record channel list
3512 \param - pNumChannels Pointer to number of roam scan channels
3513
3514 \return - 0 for success non-zero for failure
3515
3516 --------------------------------------------------------------------------*/
3517VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
3518{
3519 tANI_U8 *inPtr = pValue;
3520 int tempInt;
3521 int j = 0;
3522 int v = 0;
3523 char buf[32];
3524
3525 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3526 /*no argument after the command*/
3527 if (NULL == inPtr)
3528 {
3529 return -EINVAL;
3530 }
3531
3532 /*no space after the command*/
3533 else if (SPACE_ASCII_VALUE != *inPtr)
3534 {
3535 return -EINVAL;
3536 }
3537
3538 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003539 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003540
3541 /*no argument followed by spaces*/
3542 if ('\0' == *inPtr)
3543 {
3544 return -EINVAL;
3545 }
3546
3547 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003548 v = sscanf(inPtr, "%32s ", buf);
3549 if (1 != v) return -EINVAL;
3550
Srinivas Girigowdade697412013-02-14 16:31:48 -08003551 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003552 if ((v < 0) ||
3553 (tempInt <= 0) ||
3554 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
3555 {
3556 return -EINVAL;
3557 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003558
3559 *pNumChannels = tempInt;
3560
3561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3562 "Number of channels are: %d", *pNumChannels);
3563
3564 for (j = 0; j < (*pNumChannels); j++)
3565 {
3566 /*inPtr pointing to the beginning of first space after number of channels*/
3567 inPtr = strpbrk( inPtr, " " );
3568 /*no channel list after the number of channels argument*/
3569 if (NULL == inPtr)
3570 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003571 if (0 != j)
3572 {
3573 *pNumChannels = j;
3574 return VOS_STATUS_SUCCESS;
3575 }
3576 else
3577 {
3578 return -EINVAL;
3579 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003580 }
3581
3582 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003583 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003584
3585 /*no channel list after the number of channels argument and spaces*/
3586 if ( '\0' == *inPtr )
3587 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003588 if (0 != j)
3589 {
3590 *pNumChannels = j;
3591 return VOS_STATUS_SUCCESS;
3592 }
3593 else
3594 {
3595 return -EINVAL;
3596 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003597 }
3598
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003599 v = sscanf(inPtr, "%32s ", buf);
3600 if (1 != v) return -EINVAL;
3601
Srinivas Girigowdade697412013-02-14 16:31:48 -08003602 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003603 if ((v < 0) ||
3604 (tempInt <= 0) ||
3605 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3606 {
3607 return -EINVAL;
3608 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003609 pChannelList[j] = tempInt;
3610
3611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3612 "Channel %d added to preferred channel list",
3613 pChannelList[j] );
3614 }
3615
Srinivas Girigowdade697412013-02-14 16:31:48 -08003616 return VOS_STATUS_SUCCESS;
3617}
3618
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003619
3620/**---------------------------------------------------------------------------
3621
3622 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
3623
3624 This function parses the reasoc command data passed in the format
3625 REASSOC<space><bssid><space><channel>
3626
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003627 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003628 \param - pTargetApBssid Pointer to target Ap bssid
3629 \param - pChannel Pointer to the Target AP channel
3630
3631 \return - 0 for success non-zero for failure
3632
3633 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003634VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
3635 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003636{
3637 tANI_U8 *inPtr = pValue;
3638 int tempInt;
3639 int v = 0;
3640 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003641 /* 12 hexa decimal digits and 5 ':' */
3642 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003643
3644 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3645 /*no argument after the command*/
3646 if (NULL == inPtr)
3647 {
3648 return -EINVAL;
3649 }
3650
3651 /*no space after the command*/
3652 else if (SPACE_ASCII_VALUE != *inPtr)
3653 {
3654 return -EINVAL;
3655 }
3656
3657 /*removing empty spaces*/
3658 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3659
3660 /*no argument followed by spaces*/
3661 if ('\0' == *inPtr)
3662 {
3663 return -EINVAL;
3664 }
3665
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003666 v = sscanf(inPtr, "%17s", macAddress);
3667 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003668 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3670 "Invalid MAC address or All hex inputs are not read (%d)", v);
3671 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003672 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003673
3674 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3675 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3676 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3677 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3678 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3679 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003680
3681 /* point to the next argument */
3682 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3683 /*no argument after the command*/
3684 if (NULL == inPtr) return -EINVAL;
3685
3686 /*removing empty spaces*/
3687 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3688
3689 /*no argument followed by spaces*/
3690 if ('\0' == *inPtr)
3691 {
3692 return -EINVAL;
3693 }
3694
3695 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003696 v = sscanf(inPtr, "%32s ", tempBuf);
3697 if (1 != v) return -EINVAL;
3698
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003699 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003700 if ((v < 0) ||
3701 (tempInt <= 0) ||
3702 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3703 {
3704 return -EINVAL;
3705 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003706
3707 *pChannel = tempInt;
3708 return VOS_STATUS_SUCCESS;
3709}
3710
3711#endif
3712
Jeff Johnson295189b2012-06-20 16:38:30 -07003713/**---------------------------------------------------------------------------
3714
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003715 \brief hdd_is_valid_mac_address() - Validate MAC address
3716
3717 This function validates whether the given MAC address is valid or not
3718 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
3719 where X is the hexa decimal digit character and separated by ':'
3720 This algorithm works even if MAC address is not separated by ':'
3721
3722 This code checks given input string mac contains exactly 12 hexadecimal digits.
3723 and a separator colon : appears in the input string only after
3724 an even number of hex digits.
3725
3726 \param - pMacAddr pointer to the input MAC address
3727 \return - 1 for valid and 0 for invalid
3728
3729 --------------------------------------------------------------------------*/
3730
3731v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
3732{
3733 int xdigit = 0;
3734 int separator = 0;
3735 while (*pMacAddr)
3736 {
3737 if (isxdigit(*pMacAddr))
3738 {
3739 xdigit++;
3740 }
3741 else if (':' == *pMacAddr)
3742 {
3743 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
3744 break;
3745
3746 ++separator;
3747 }
3748 else
3749 {
3750 separator = -1;
3751 /* Invalid MAC found */
3752 return 0;
3753 }
3754 ++pMacAddr;
3755 }
3756 return (xdigit == 12 && (separator == 5 || separator == 0));
3757}
3758
3759/**---------------------------------------------------------------------------
3760
Jeff Johnson295189b2012-06-20 16:38:30 -07003761 \brief hdd_open() - HDD Open function
3762
3763 This is called in response to ifconfig up
3764
3765 \param - dev Pointer to net_device structure
3766
3767 \return - 0 for success non-zero for failure
3768
3769 --------------------------------------------------------------------------*/
3770int hdd_open (struct net_device *dev)
3771{
3772 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3773 hdd_context_t *pHddCtx;
3774 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3775 VOS_STATUS status;
3776 v_BOOL_t in_standby = TRUE;
3777
3778 if (NULL == pAdapter)
3779 {
3780 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003781 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003782 return -ENODEV;
3783 }
3784
3785 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3786 if (NULL == pHddCtx)
3787 {
3788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003789 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003790 return -ENODEV;
3791 }
3792
3793 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3794 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
3795 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003796 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
3797 {
3798 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05303799 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003800 in_standby = FALSE;
3801 break;
3802 }
3803 else
3804 {
3805 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3806 pAdapterNode = pNext;
3807 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003808 }
3809
3810 if (TRUE == in_standby)
3811 {
3812 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
3813 {
3814 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
3815 "wlan out of power save", __func__);
3816 return -EINVAL;
3817 }
3818 }
3819
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003820 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07003821 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3822 {
3823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003824 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003825 /* Enable TX queues only when we are connected */
3826 netif_tx_start_all_queues(dev);
3827 }
3828
3829 return 0;
3830}
3831
3832int hdd_mon_open (struct net_device *dev)
3833{
3834 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3835
3836 if(pAdapter == NULL) {
3837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003838 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003839 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003840 }
3841
3842 netif_start_queue(dev);
3843
3844 return 0;
3845}
3846/**---------------------------------------------------------------------------
3847
3848 \brief hdd_stop() - HDD stop function
3849
3850 This is called in response to ifconfig down
3851
3852 \param - dev Pointer to net_device structure
3853
3854 \return - 0 for success non-zero for failure
3855
3856 --------------------------------------------------------------------------*/
3857
3858int hdd_stop (struct net_device *dev)
3859{
3860 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3861 hdd_context_t *pHddCtx;
3862 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3863 VOS_STATUS status;
3864 v_BOOL_t enter_standby = TRUE;
3865
3866 ENTER();
3867
3868 if (NULL == pAdapter)
3869 {
3870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003871 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003872 return -ENODEV;
3873 }
3874
3875 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3876 if (NULL == pHddCtx)
3877 {
3878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003879 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003880 return -ENODEV;
3881 }
3882
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003883 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07003884 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
3885 netif_tx_disable(pAdapter->dev);
3886 netif_carrier_off(pAdapter->dev);
3887
3888
3889 /* SoftAP ifaces should never go in power save mode
3890 making sure same here. */
3891 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
3892 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07003893 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07003894 )
3895 {
3896 /* SoftAP mode, so return from here */
3897 EXIT();
3898 return 0;
3899 }
3900
3901 /* Find if any iface is up then
3902 if any iface is up then can't put device to sleep/ power save mode. */
3903 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3904 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
3905 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003906 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
3907 {
3908 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05303909 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003910 enter_standby = FALSE;
3911 break;
3912 }
3913 else
3914 {
3915 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3916 pAdapterNode = pNext;
3917 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003918 }
3919
3920 if (TRUE == enter_standby)
3921 {
3922 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
3923 "entering standby", __func__);
3924 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
3925 {
3926 /*log and return success*/
3927 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
3928 "wlan in power save", __func__);
3929 }
3930 }
3931
3932 EXIT();
3933 return 0;
3934}
3935
3936/**---------------------------------------------------------------------------
3937
3938 \brief hdd_uninit() - HDD uninit function
3939
3940 This is called during the netdev unregister to uninitialize all data
3941associated with the device
3942
3943 \param - dev Pointer to net_device structure
3944
3945 \return - void
3946
3947 --------------------------------------------------------------------------*/
3948static void hdd_uninit (struct net_device *dev)
3949{
3950 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3951
3952 ENTER();
3953
3954 do
3955 {
3956 if (NULL == pAdapter)
3957 {
3958 hddLog(VOS_TRACE_LEVEL_FATAL,
3959 "%s: NULL pAdapter", __func__);
3960 break;
3961 }
3962
3963 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3964 {
3965 hddLog(VOS_TRACE_LEVEL_FATAL,
3966 "%s: Invalid magic", __func__);
3967 break;
3968 }
3969
3970 if (NULL == pAdapter->pHddCtx)
3971 {
3972 hddLog(VOS_TRACE_LEVEL_FATAL,
3973 "%s: NULL pHddCtx", __func__);
3974 break;
3975 }
3976
3977 if (dev != pAdapter->dev)
3978 {
3979 hddLog(VOS_TRACE_LEVEL_FATAL,
3980 "%s: Invalid device reference", __func__);
3981 /* we haven't validated all cases so let this go for now */
3982 }
3983
3984 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
3985
3986 /* after uninit our adapter structure will no longer be valid */
3987 pAdapter->dev = NULL;
3988 pAdapter->magic = 0;
3989 } while (0);
3990
3991 EXIT();
3992}
3993
3994/**---------------------------------------------------------------------------
3995
3996 \brief hdd_release_firmware() -
3997
3998 This function calls the release firmware API to free the firmware buffer.
3999
4000 \param - pFileName Pointer to the File Name.
4001 pCtx - Pointer to the adapter .
4002
4003
4004 \return - 0 for success, non zero for failure
4005
4006 --------------------------------------------------------------------------*/
4007
4008VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4009{
4010 VOS_STATUS status = VOS_STATUS_SUCCESS;
4011 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4012 ENTER();
4013
4014
4015 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4016
4017 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4018
4019 if(pHddCtx->fw) {
4020 release_firmware(pHddCtx->fw);
4021 pHddCtx->fw = NULL;
4022 }
4023 else
4024 status = VOS_STATUS_E_FAILURE;
4025 }
4026 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4027 if(pHddCtx->nv) {
4028 release_firmware(pHddCtx->nv);
4029 pHddCtx->nv = NULL;
4030 }
4031 else
4032 status = VOS_STATUS_E_FAILURE;
4033
4034 }
4035
4036 EXIT();
4037 return status;
4038}
4039
4040/**---------------------------------------------------------------------------
4041
4042 \brief hdd_request_firmware() -
4043
4044 This function reads the firmware file using the request firmware
4045 API and returns the the firmware data and the firmware file size.
4046
4047 \param - pfileName - Pointer to the file name.
4048 - pCtx - Pointer to the adapter .
4049 - ppfw_data - Pointer to the pointer of the firmware data.
4050 - pSize - Pointer to the file size.
4051
4052 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4053
4054 --------------------------------------------------------------------------*/
4055
4056
4057VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4058{
4059 int status;
4060 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4061 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4062 ENTER();
4063
4064 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4065
4066 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4067
4068 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4069 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4070 __func__, pfileName);
4071 retval = VOS_STATUS_E_FAILURE;
4072 }
4073
4074 else {
4075 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4076 *pSize = pHddCtx->fw->size;
4077 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4078 __func__, *pSize);
4079 }
4080 }
4081 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4082
4083 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4084
4085 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4086 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4087 __func__, pfileName);
4088 retval = VOS_STATUS_E_FAILURE;
4089 }
4090
4091 else {
4092 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4093 *pSize = pHddCtx->nv->size;
4094 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4095 __func__, *pSize);
4096 }
4097 }
4098
4099 EXIT();
4100 return retval;
4101}
4102/**---------------------------------------------------------------------------
4103 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4104
4105 This is the function invoked by SME to inform the result of a full power
4106 request issued by HDD
4107
4108 \param - callbackcontext - Pointer to cookie
4109 status - result of request
4110
4111 \return - None
4112
4113--------------------------------------------------------------------------*/
4114void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4115{
4116 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4117
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004118 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004119 if(&pHddCtx->full_pwr_comp_var)
4120 {
4121 complete(&pHddCtx->full_pwr_comp_var);
4122 }
4123}
4124
4125/**---------------------------------------------------------------------------
4126
4127 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4128
4129 This is the function invoked by SME to inform the result of BMPS
4130 request issued by HDD
4131
4132 \param - callbackcontext - Pointer to cookie
4133 status - result of request
4134
4135 \return - None
4136
4137--------------------------------------------------------------------------*/
4138void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4139{
4140
4141 struct completion *completion_var = (struct completion*) callbackContext;
4142
4143 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4144 if(completion_var != NULL)
4145 {
4146 complete(completion_var);
4147 }
4148}
4149
4150/**---------------------------------------------------------------------------
4151
4152 \brief hdd_get_cfg_file_size() -
4153
4154 This function reads the configuration file using the request firmware
4155 API and returns the configuration file size.
4156
4157 \param - pCtx - Pointer to the adapter .
4158 - pFileName - Pointer to the file name.
4159 - pBufSize - Pointer to the buffer size.
4160
4161 \return - 0 for success, non zero for failure
4162
4163 --------------------------------------------------------------------------*/
4164
4165VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4166{
4167 int status;
4168 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4169
4170 ENTER();
4171
4172 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4173
4174 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4175 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4176 status = VOS_STATUS_E_FAILURE;
4177 }
4178 else {
4179 *pBufSize = pHddCtx->fw->size;
4180 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4181 release_firmware(pHddCtx->fw);
4182 pHddCtx->fw = NULL;
4183 }
4184
4185 EXIT();
4186 return VOS_STATUS_SUCCESS;
4187}
4188
4189/**---------------------------------------------------------------------------
4190
4191 \brief hdd_read_cfg_file() -
4192
4193 This function reads the configuration file using the request firmware
4194 API and returns the cfg data and the buffer size of the configuration file.
4195
4196 \param - pCtx - Pointer to the adapter .
4197 - pFileName - Pointer to the file name.
4198 - pBuffer - Pointer to the data buffer.
4199 - pBufSize - Pointer to the buffer size.
4200
4201 \return - 0 for success, non zero for failure
4202
4203 --------------------------------------------------------------------------*/
4204
4205VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4206 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4207{
4208 int status;
4209 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4210
4211 ENTER();
4212
4213 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4214
4215 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4216 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4217 return VOS_STATUS_E_FAILURE;
4218 }
4219 else {
4220 if(*pBufSize != pHddCtx->fw->size) {
4221 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4222 "file size", __func__);
4223 release_firmware(pHddCtx->fw);
4224 pHddCtx->fw = NULL;
4225 return VOS_STATUS_E_FAILURE;
4226 }
4227 else {
4228 if(pBuffer) {
4229 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4230 }
4231 release_firmware(pHddCtx->fw);
4232 pHddCtx->fw = NULL;
4233 }
4234 }
4235
4236 EXIT();
4237
4238 return VOS_STATUS_SUCCESS;
4239}
4240
4241/**---------------------------------------------------------------------------
4242
Jeff Johnson295189b2012-06-20 16:38:30 -07004243 \brief hdd_set_mac_address() -
4244
4245 This function sets the user specified mac address using
4246 the command ifconfig wlanX hw ether <mac adress>.
4247
4248 \param - dev - Pointer to the net device.
4249 - addr - Pointer to the sockaddr.
4250 \return - 0 for success, non zero for failure
4251
4252 --------------------------------------------------------------------------*/
4253
4254static int hdd_set_mac_address(struct net_device *dev, void *addr)
4255{
4256 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4257 struct sockaddr *psta_mac_addr = addr;
4258 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4259
4260 ENTER();
4261
4262 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4263
4264#ifdef HDD_SESSIONIZE
4265 // set the MAC address though the STA ID CFG.
4266 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4267 (v_U8_t *)&pAdapter->macAddressCurrent,
4268 sizeof( pAdapter->macAddressCurrent ),
4269 hdd_set_mac_addr_cb, VOS_FALSE );
4270#endif
4271
4272 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4273
4274 EXIT();
4275 return halStatus;
4276}
4277
4278tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4279{
4280 int i;
4281 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4282 {
4283 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4284 break;
4285 }
4286
4287 if( VOS_MAX_CONCURRENCY_PERSONA == i)
4288 return NULL;
4289
4290 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
4291 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
4292}
4293
4294void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
4295{
4296 int i;
4297 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4298 {
4299 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
4300 {
4301 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
4302 break;
4303 }
4304 }
4305 return;
4306}
4307
4308#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4309 static struct net_device_ops wlan_drv_ops = {
4310 .ndo_open = hdd_open,
4311 .ndo_stop = hdd_stop,
4312 .ndo_uninit = hdd_uninit,
4313 .ndo_start_xmit = hdd_hard_start_xmit,
4314 .ndo_tx_timeout = hdd_tx_timeout,
4315 .ndo_get_stats = hdd_stats,
4316 .ndo_do_ioctl = hdd_ioctl,
4317 .ndo_set_mac_address = hdd_set_mac_address,
4318 .ndo_select_queue = hdd_select_queue,
4319#ifdef WLAN_FEATURE_PACKET_FILTERING
4320#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
4321 .ndo_set_rx_mode = hdd_set_multicast_list,
4322#else
4323 .ndo_set_multicast_list = hdd_set_multicast_list,
4324#endif //LINUX_VERSION_CODE
4325#endif
4326 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004327 static struct net_device_ops wlan_mon_drv_ops = {
4328 .ndo_open = hdd_mon_open,
4329 .ndo_stop = hdd_stop,
4330 .ndo_uninit = hdd_uninit,
4331 .ndo_start_xmit = hdd_mon_hard_start_xmit,
4332 .ndo_tx_timeout = hdd_tx_timeout,
4333 .ndo_get_stats = hdd_stats,
4334 .ndo_do_ioctl = hdd_ioctl,
4335 .ndo_set_mac_address = hdd_set_mac_address,
4336 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004337
4338#endif
4339
4340void hdd_set_station_ops( struct net_device *pWlanDev )
4341{
4342#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4343 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
4344 pWlanDev->netdev_ops = &wlan_drv_ops;
4345#else
4346 pWlanDev->open = hdd_open;
4347 pWlanDev->stop = hdd_stop;
4348 pWlanDev->uninit = hdd_uninit;
4349 pWlanDev->hard_start_xmit = NULL;
4350 pWlanDev->tx_timeout = hdd_tx_timeout;
4351 pWlanDev->get_stats = hdd_stats;
4352 pWlanDev->do_ioctl = hdd_ioctl;
4353 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
4354 pWlanDev->set_mac_address = hdd_set_mac_address;
4355#endif
4356}
4357
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004358static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07004359{
4360 struct net_device *pWlanDev = NULL;
4361 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004362 /*
4363 * cfg80211 initialization and registration....
4364 */
4365 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
4366
Jeff Johnson295189b2012-06-20 16:38:30 -07004367 if(pWlanDev != NULL)
4368 {
4369
4370 //Save the pointer to the net_device in the HDD adapter
4371 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
4372
Jeff Johnson295189b2012-06-20 16:38:30 -07004373 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
4374
4375 pAdapter->dev = pWlanDev;
4376 pAdapter->pHddCtx = pHddCtx;
4377 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
4378
4379 init_completion(&pAdapter->session_open_comp_var);
4380 init_completion(&pAdapter->session_close_comp_var);
4381 init_completion(&pAdapter->disconnect_comp_var);
4382 init_completion(&pAdapter->linkup_event_var);
4383 init_completion(&pAdapter->cancel_rem_on_chan_var);
4384 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004385#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4386 init_completion(&pAdapter->offchannel_tx_event);
4387#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004388 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004389#ifdef FEATURE_WLAN_TDLS
4390 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07004391 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08004392 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05304393 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004394#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004395 init_completion(&pHddCtx->mc_sus_event_var);
4396 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05304397 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07004398 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07004399 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07004400
Rajeev79dbe4c2013-10-05 11:03:42 +05304401#ifdef FEATURE_WLAN_BATCH_SCAN
4402 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
4403 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
4404 pAdapter->pBatchScanRsp = NULL;
4405 pAdapter->numScanList = 0;
4406 mutex_init(&pAdapter->hdd_batch_scan_lock);
4407#endif
4408
Jeff Johnson295189b2012-06-20 16:38:30 -07004409 pAdapter->isLinkUpSvcNeeded = FALSE;
4410 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
4411 //Init the net_device structure
4412 strlcpy(pWlanDev->name, name, IFNAMSIZ);
4413
4414 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
4415 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
4416 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
4417 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
4418
4419 hdd_set_station_ops( pAdapter->dev );
4420
4421 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004422 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
4423 pAdapter->wdev.wiphy = pHddCtx->wiphy;
4424 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004425 /* set pWlanDev's parent to underlying device */
4426 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
4427 }
4428
4429 return pAdapter;
4430}
4431
4432VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
4433{
4434 struct net_device *pWlanDev = pAdapter->dev;
4435 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4436 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4437 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4438
4439 if( rtnl_lock_held )
4440 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08004441 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07004442 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
4443 {
4444 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
4445 return VOS_STATUS_E_FAILURE;
4446 }
4447 }
4448 if (register_netdevice(pWlanDev))
4449 {
4450 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
4451 return VOS_STATUS_E_FAILURE;
4452 }
4453 }
4454 else
4455 {
4456 if(register_netdev(pWlanDev))
4457 {
4458 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
4459 return VOS_STATUS_E_FAILURE;
4460 }
4461 }
4462 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
4463
4464 return VOS_STATUS_SUCCESS;
4465}
4466
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004467static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07004468{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004469 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07004470
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004471 if (NULL == pAdapter)
4472 {
4473 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
4474 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07004475 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004476
4477 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4478 {
4479 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
4480 return eHAL_STATUS_NOT_INITIALIZED;
4481 }
4482
4483 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
4484
4485 /* need to make sure all of our scheduled work has completed.
4486 * This callback is called from MC thread context, so it is safe to
4487 * to call below flush workqueue API from here.
4488 */
4489 flush_scheduled_work();
4490
4491 /* We can be blocked while waiting for scheduled work to be
4492 * flushed, and the adapter structure can potentially be freed, in
4493 * which case the magic will have been reset. So make sure the
4494 * magic is still good, and hence the adapter structure is still
4495 * valid, before signaling completion */
4496 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
4497 {
4498 complete(&pAdapter->session_close_comp_var);
4499 }
4500
Jeff Johnson295189b2012-06-20 16:38:30 -07004501 return eHAL_STATUS_SUCCESS;
4502}
4503
4504VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
4505{
4506 struct net_device *pWlanDev = pAdapter->dev;
4507 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4508 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4509 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4510 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4511 int rc = 0;
4512
4513 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004514 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07004515 //Open a SME session for future operation
4516 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004517 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004518 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4519 {
4520 hddLog(VOS_TRACE_LEVEL_FATAL,
4521 "sme_OpenSession() failed with status code %08d [x%08lx]",
4522 halStatus, halStatus );
4523 status = VOS_STATUS_E_FAILURE;
4524 goto error_sme_open;
4525 }
4526
4527 //Block on a completion variable. Can't wait forever though.
4528 rc = wait_for_completion_interruptible_timeout(
4529 &pAdapter->session_open_comp_var,
4530 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4531 if (!rc)
4532 {
4533 hddLog(VOS_TRACE_LEVEL_FATAL,
4534 "Session is not opened within timeout period code %08d", rc );
4535 status = VOS_STATUS_E_FAILURE;
4536 goto error_sme_open;
4537 }
4538
4539 // Register wireless extensions
4540 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
4541 {
4542 hddLog(VOS_TRACE_LEVEL_FATAL,
4543 "hdd_register_wext() failed with status code %08d [x%08lx]",
4544 halStatus, halStatus );
4545 status = VOS_STATUS_E_FAILURE;
4546 goto error_register_wext;
4547 }
4548 //Safe to register the hard_start_xmit function again
4549#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4550 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
4551#else
4552 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
4553#endif
4554
4555 //Set the Connection State to Not Connected
4556 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4557
4558 //Set the default operation channel
4559 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
4560
4561 /* Make the default Auth Type as OPEN*/
4562 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4563
4564 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
4565 {
4566 hddLog(VOS_TRACE_LEVEL_FATAL,
4567 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
4568 status, status );
4569 goto error_init_txrx;
4570 }
4571
4572 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4573
4574 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
4575 {
4576 hddLog(VOS_TRACE_LEVEL_FATAL,
4577 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
4578 status, status );
4579 goto error_wmm_init;
4580 }
4581
4582 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4583
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004584#ifdef FEATURE_WLAN_TDLS
4585 if(0 != wlan_hdd_tdls_init(pAdapter))
4586 {
4587 status = VOS_STATUS_E_FAILURE;
4588 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
4589 goto error_tdls_init;
4590 }
4591 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
4592#endif
4593
Jeff Johnson295189b2012-06-20 16:38:30 -07004594 return VOS_STATUS_SUCCESS;
4595
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004596#ifdef FEATURE_WLAN_TDLS
4597error_tdls_init:
4598 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4599 hdd_wmm_adapter_close(pAdapter);
4600#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004601error_wmm_init:
4602 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4603 hdd_deinit_tx_rx(pAdapter);
4604error_init_txrx:
4605 hdd_UnregisterWext(pWlanDev);
4606error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004607 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07004608 {
4609 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004610 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07004611 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004612 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07004613 {
4614 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004615 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004616 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004617 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07004618 }
4619}
4620error_sme_open:
4621 return status;
4622}
4623
Jeff Johnson295189b2012-06-20 16:38:30 -07004624void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4625{
4626 hdd_cfg80211_state_t *cfgState;
4627
4628 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
4629
4630 if( NULL != cfgState->buf )
4631 {
4632 int rc;
4633 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
4634 rc = wait_for_completion_interruptible_timeout(
4635 &pAdapter->tx_action_cnf_event,
4636 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
4637 if(!rc)
4638 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08004639 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004640 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
4641 }
4642 }
4643 return;
4644}
Jeff Johnson295189b2012-06-20 16:38:30 -07004645
4646void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4647{
4648 ENTER();
4649 switch ( pAdapter->device_mode )
4650 {
4651 case WLAN_HDD_INFRA_STATION:
4652 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004653 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004654 {
4655 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
4656 {
4657 hdd_deinit_tx_rx( pAdapter );
4658 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4659 }
4660
4661 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
4662 {
4663 hdd_wmm_adapter_close( pAdapter );
4664 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4665 }
4666
Jeff Johnson295189b2012-06-20 16:38:30 -07004667 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004668#ifdef FEATURE_WLAN_TDLS
4669 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
4670 {
4671 wlan_hdd_tdls_exit(pAdapter);
4672 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
4673 }
4674#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004675
4676 break;
4677 }
4678
4679 case WLAN_HDD_SOFTAP:
4680 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004681 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05304682
4683 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
4684 {
4685 hdd_wmm_adapter_close( pAdapter );
4686 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4687 }
4688
Jeff Johnson295189b2012-06-20 16:38:30 -07004689 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004690
4691 hdd_unregister_hostapd(pAdapter);
4692 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07004693 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07004694 break;
4695 }
4696
4697 case WLAN_HDD_MONITOR:
4698 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004699 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07004700 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
4701 {
4702 hdd_deinit_tx_rx( pAdapter );
4703 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4704 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004705 if(NULL != pAdapterforTx)
4706 {
4707 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
4708 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004709 break;
4710 }
4711
4712
4713 default:
4714 break;
4715 }
4716
4717 EXIT();
4718}
4719
4720void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
4721{
4722 struct net_device *pWlanDev = pAdapter->dev;
4723
Rajeev79dbe4c2013-10-05 11:03:42 +05304724#ifdef FEATURE_WLAN_BATCH_SCAN
4725 tHddBatchScanRsp *pNode;
4726 tHddBatchScanRsp *pPrev;
4727 if (pAdapter)
4728 {
4729 mutex_lock(&pAdapter->hdd_batch_scan_lock);
4730 pNode = pAdapter->pBatchScanRsp;
4731 while (pNode)
4732 {
4733 pPrev = pNode;
4734 pNode = pNode->pNext;
4735 vos_mem_free((v_VOID_t * )pPrev);
4736 }
4737 pAdapter->pBatchScanRsp = NULL;
4738 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
4739 }
4740#endif
4741
Jeff Johnson295189b2012-06-20 16:38:30 -07004742 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
4743 if( rtnl_held )
4744 {
4745 unregister_netdevice(pWlanDev);
4746 }
4747 else
4748 {
4749 unregister_netdev(pWlanDev);
4750 }
4751 // note that the pAdapter is no longer valid at this point
4752 // since the memory has been reclaimed
4753 }
4754
4755}
4756
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004757void hdd_set_pwrparams(hdd_context_t *pHddCtx)
4758{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304759 VOS_STATUS status;
4760 hdd_adapter_t *pAdapter = NULL;
4761 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004762
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304763 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004764
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304765 /*loop through all adapters.*/
4766 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004767 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304768 pAdapter = pAdapterNode->pAdapter;
4769 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
4770 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004771
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304772 { // we skip this registration for modes other than STA and P2P client modes.
4773 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4774 pAdapterNode = pNext;
4775 continue;
4776 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004777
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304778 //Apply Dynamic DTIM For P2P
4779 //Only if ignoreDynamicDtimInP2pMode is not set in ini
4780 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
4781 pHddCtx->cfg_ini->enableModulatedDTIM) &&
4782 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4783 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
4784 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
4785 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
4786 (eConnectionState_Associated ==
4787 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
4788 (pHddCtx->cfg_ini->fIsBmpsEnabled))
4789 {
4790 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004791
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304792 powerRequest.uIgnoreDTIM = 1;
4793 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
4794
4795 if (pHddCtx->cfg_ini->enableModulatedDTIM)
4796 {
4797 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
4798 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
4799 }
4800 else
4801 {
4802 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
4803 }
4804
4805 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
4806 * specified during Enter/Exit BMPS when LCD off*/
4807 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
4808 NULL, eANI_BOOLEAN_FALSE);
4809 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
4810 NULL, eANI_BOOLEAN_FALSE);
4811
4812 /* switch to the DTIM specified in cfg.ini */
4813 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4814 "Switch to DTIM %d", powerRequest.uListenInterval);
4815 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
4816 break;
4817
4818 }
4819
4820 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4821 pAdapterNode = pNext;
4822 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004823}
4824
4825void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
4826{
4827 /*Switch back to DTIM 1*/
4828 tSirSetPowerParamsReq powerRequest = { 0 };
4829
4830 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
4831 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07004832 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004833
4834 /* Update ignoreDTIM and ListedInterval in CFG with default values */
4835 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
4836 NULL, eANI_BOOLEAN_FALSE);
4837 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
4838 NULL, eANI_BOOLEAN_FALSE);
4839
4840 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4841 "Switch to DTIM%d",powerRequest.uListenInterval);
4842 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
4843
4844}
4845
Jeff Johnson295189b2012-06-20 16:38:30 -07004846VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
4847{
4848 VOS_STATUS status = VOS_STATUS_SUCCESS;
4849
4850 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
4851 {
4852 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4853 }
4854
4855 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
4856 {
4857 sme_StartAutoBmpsTimer(pHddCtx->hHal);
4858 }
4859
4860 if (pHddCtx->cfg_ini->fIsImpsEnabled)
4861 {
4862 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4863 }
4864
4865 return status;
4866}
4867
4868VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
4869{
4870 hdd_adapter_t *pAdapter = NULL;
4871 eHalStatus halStatus;
4872 VOS_STATUS status = VOS_STATUS_E_INVAL;
4873 v_BOOL_t disableBmps = FALSE;
4874 v_BOOL_t disableImps = FALSE;
4875
4876 switch(session_type)
4877 {
4878 case WLAN_HDD_INFRA_STATION:
4879 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07004880 case WLAN_HDD_P2P_CLIENT:
4881 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004882 //Exit BMPS -> Is Sta/P2P Client is already connected
4883 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
4884 if((NULL != pAdapter)&&
4885 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4886 {
4887 disableBmps = TRUE;
4888 }
4889
4890 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4891 if((NULL != pAdapter)&&
4892 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4893 {
4894 disableBmps = TRUE;
4895 }
4896
4897 //Exit both Bmps and Imps incase of Go/SAP Mode
4898 if((WLAN_HDD_SOFTAP == session_type) ||
4899 (WLAN_HDD_P2P_GO == session_type))
4900 {
4901 disableBmps = TRUE;
4902 disableImps = TRUE;
4903 }
4904
4905 if(TRUE == disableImps)
4906 {
4907 if (pHddCtx->cfg_ini->fIsImpsEnabled)
4908 {
4909 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4910 }
4911 }
4912
4913 if(TRUE == disableBmps)
4914 {
4915 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
4916 {
4917 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4918
4919 if(eHAL_STATUS_SUCCESS != halStatus)
4920 {
4921 status = VOS_STATUS_E_FAILURE;
4922 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
4923 VOS_ASSERT(0);
4924 return status;
4925 }
4926 }
4927
4928 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
4929 {
4930 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
4931
4932 if(eHAL_STATUS_SUCCESS != halStatus)
4933 {
4934 status = VOS_STATUS_E_FAILURE;
4935 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
4936 VOS_ASSERT(0);
4937 return status;
4938 }
4939 }
4940 }
4941
4942 if((TRUE == disableBmps) ||
4943 (TRUE == disableImps))
4944 {
4945 /* Now, get the chip into Full Power now */
4946 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
4947 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
4948 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
4949
4950 if(halStatus != eHAL_STATUS_SUCCESS)
4951 {
4952 if(halStatus == eHAL_STATUS_PMC_PENDING)
4953 {
4954 //Block on a completion variable. Can't wait forever though
4955 wait_for_completion_interruptible_timeout(
4956 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
4957 }
4958 else
4959 {
4960 status = VOS_STATUS_E_FAILURE;
4961 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
4962 VOS_ASSERT(0);
4963 return status;
4964 }
4965 }
4966
4967 status = VOS_STATUS_SUCCESS;
4968 }
4969
4970 break;
4971 }
4972 return status;
4973}
4974
4975hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004976 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07004977 tANI_U8 rtnl_held )
4978{
4979 hdd_adapter_t *pAdapter = NULL;
4980 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
4981 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4982 VOS_STATUS exitbmpsStatus;
4983
4984 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
4985
4986 //Disable BMPS incase of Concurrency
4987 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
4988
4989 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
4990 {
4991 //Fail to Exit BMPS
4992 VOS_ASSERT(0);
4993 return NULL;
4994 }
4995
4996 switch(session_type)
4997 {
4998 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07004999 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005000 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005001 {
5002 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5003
5004 if( NULL == pAdapter )
5005 return NULL;
5006
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305007#ifdef FEATURE_WLAN_TDLS
5008 /* A Mutex Lock is introduced while changing/initializing the mode to
5009 * protect the concurrent access for the Adapters by TDLS module.
5010 */
5011 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5012 {
5013 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5014 "%s: unable to lock list", __func__);
5015 return NULL;
5016 }
5017#endif
5018
Jeff Johnsone7245742012-09-05 17:12:55 -07005019 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5020 NL80211_IFTYPE_P2P_CLIENT:
5021 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005022
Jeff Johnson295189b2012-06-20 16:38:30 -07005023 pAdapter->device_mode = session_type;
5024
5025 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305026#ifdef FEATURE_WLAN_TDLS
5027 mutex_unlock(&pHddCtx->tdls_lock);
5028#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005029 if( VOS_STATUS_SUCCESS != status )
5030 goto err_free_netdev;
5031
5032 status = hdd_register_interface( pAdapter, rtnl_held );
5033 if( VOS_STATUS_SUCCESS != status )
5034 {
5035 hdd_deinit_adapter(pHddCtx, pAdapter);
5036 goto err_free_netdev;
5037 }
5038 //Stop the Interface TX queue.
5039 netif_tx_disable(pAdapter->dev);
5040 //netif_tx_disable(pWlanDev);
5041 netif_carrier_off(pAdapter->dev);
5042
5043 break;
5044 }
5045
Jeff Johnson295189b2012-06-20 16:38:30 -07005046 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005047 case WLAN_HDD_SOFTAP:
5048 {
5049 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5050 if( NULL == pAdapter )
5051 return NULL;
5052
Jeff Johnson295189b2012-06-20 16:38:30 -07005053 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5054 NL80211_IFTYPE_AP:
5055 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005056 pAdapter->device_mode = session_type;
5057
5058 status = hdd_init_ap_mode(pAdapter);
5059 if( VOS_STATUS_SUCCESS != status )
5060 goto err_free_netdev;
5061
5062 status = hdd_register_hostapd( pAdapter, rtnl_held );
5063 if( VOS_STATUS_SUCCESS != status )
5064 {
5065 hdd_deinit_adapter(pHddCtx, pAdapter);
5066 goto err_free_netdev;
5067 }
5068
5069 netif_tx_disable(pAdapter->dev);
5070 netif_carrier_off(pAdapter->dev);
5071
5072 hdd_set_conparam( 1 );
5073 break;
5074 }
5075 case WLAN_HDD_MONITOR:
5076 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005077 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5078 if( NULL == pAdapter )
5079 return NULL;
5080
5081 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5082 pAdapter->device_mode = session_type;
5083 status = hdd_register_interface( pAdapter, rtnl_held );
5084#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5085 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5086#else
5087 pAdapter->dev->open = hdd_mon_open;
5088 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5089#endif
5090 hdd_init_tx_rx( pAdapter );
5091 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5092 //Set adapter to be used for data tx. It will use either GO or softap.
5093 pAdapter->sessionCtx.monitor.pAdapterForTx =
5094 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005095 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5096 {
5097 pAdapter->sessionCtx.monitor.pAdapterForTx =
5098 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5099 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005100 /* This workqueue will be used to transmit management packet over
5101 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005102 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5103 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5104 return NULL;
5105 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005106
Jeff Johnson295189b2012-06-20 16:38:30 -07005107 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5108 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005109 }
5110 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005111 case WLAN_HDD_FTM:
5112 {
5113 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5114
5115 if( NULL == pAdapter )
5116 return NULL;
5117 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5118 * message while loading driver in FTM mode. */
5119 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5120 pAdapter->device_mode = session_type;
5121 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305122
5123 hdd_init_tx_rx( pAdapter );
5124
5125 //Stop the Interface TX queue.
5126 netif_tx_disable(pAdapter->dev);
5127 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005128 }
5129 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005130 default:
5131 {
5132 VOS_ASSERT(0);
5133 return NULL;
5134 }
5135 }
5136
5137
5138 if( VOS_STATUS_SUCCESS == status )
5139 {
5140 //Add it to the hdd's session list.
5141 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5142 if( NULL == pHddAdapterNode )
5143 {
5144 status = VOS_STATUS_E_NOMEM;
5145 }
5146 else
5147 {
5148 pHddAdapterNode->pAdapter = pAdapter;
5149 status = hdd_add_adapter_back ( pHddCtx,
5150 pHddAdapterNode );
5151 }
5152 }
5153
5154 if( VOS_STATUS_SUCCESS != status )
5155 {
5156 if( NULL != pAdapter )
5157 {
5158 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5159 pAdapter = NULL;
5160 }
5161 if( NULL != pHddAdapterNode )
5162 {
5163 vos_mem_free( pHddAdapterNode );
5164 }
5165
5166 goto resume_bmps;
5167 }
5168
5169 if(VOS_STATUS_SUCCESS == status)
5170 {
5171 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5172
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005173 //Initialize the WoWL service
5174 if(!hdd_init_wowl(pAdapter))
5175 {
5176 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5177 goto err_free_netdev;
5178 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005179 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005180 return pAdapter;
5181
5182err_free_netdev:
5183 free_netdev(pAdapter->dev);
5184 wlan_hdd_release_intf_addr( pHddCtx,
5185 pAdapter->macAddressCurrent.bytes );
5186
5187resume_bmps:
5188 //If bmps disabled enable it
5189 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5190 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305191 if (pHddCtx->hdd_wlan_suspended)
5192 {
5193 hdd_set_pwrparams(pHddCtx);
5194 }
5195 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005196 }
5197 return NULL;
5198}
5199
5200VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5201 tANI_U8 rtnl_held )
5202{
5203 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5204 VOS_STATUS status;
5205
5206 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5207 if( VOS_STATUS_SUCCESS != status )
5208 return status;
5209
5210 while ( pCurrent->pAdapter != pAdapter )
5211 {
5212 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5213 if( VOS_STATUS_SUCCESS != status )
5214 break;
5215
5216 pCurrent = pNext;
5217 }
5218 pAdapterNode = pCurrent;
5219 if( VOS_STATUS_SUCCESS == status )
5220 {
5221 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5222 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305223
5224#ifdef FEATURE_WLAN_TDLS
5225
5226 /* A Mutex Lock is introduced while changing/initializing the mode to
5227 * protect the concurrent access for the Adapters by TDLS module.
5228 */
5229 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5230 {
5231 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5232 "%s: unable to lock list", __func__);
5233 return VOS_STATUS_E_FAILURE;
5234 }
5235#endif
5236
Jeff Johnson295189b2012-06-20 16:38:30 -07005237 hdd_remove_adapter( pHddCtx, pAdapterNode );
5238 vos_mem_free( pAdapterNode );
5239
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305240#ifdef FEATURE_WLAN_TDLS
5241 mutex_unlock(&pHddCtx->tdls_lock);
5242#endif
5243
Jeff Johnson295189b2012-06-20 16:38:30 -07005244
5245 /* If there is a single session of STA/P2P client, re-enable BMPS */
5246 if ((!vos_concurrent_sessions_running()) &&
5247 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5248 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5249 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305250 if (pHddCtx->hdd_wlan_suspended)
5251 {
5252 hdd_set_pwrparams(pHddCtx);
5253 }
5254 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005255 }
5256
5257 return VOS_STATUS_SUCCESS;
5258 }
5259
5260 return VOS_STATUS_E_FAILURE;
5261}
5262
5263VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5264{
5265 hdd_adapter_list_node_t *pHddAdapterNode;
5266 VOS_STATUS status;
5267
5268 ENTER();
5269
5270 do
5271 {
5272 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5273 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5274 {
5275 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
5276 vos_mem_free( pHddAdapterNode );
5277 }
5278 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
5279
5280 EXIT();
5281
5282 return VOS_STATUS_SUCCESS;
5283}
5284
5285void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
5286{
5287 v_U8_t addIE[1] = {0};
5288
5289 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5290 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
5291 eANI_BOOLEAN_FALSE) )
5292 {
5293 hddLog(LOGE,
5294 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
5295 }
5296
5297 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5298 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
5299 eANI_BOOLEAN_FALSE) )
5300 {
5301 hddLog(LOGE,
5302 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
5303 }
5304
5305 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5306 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
5307 eANI_BOOLEAN_FALSE) )
5308 {
5309 hddLog(LOGE,
5310 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
5311 }
5312}
5313
5314VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5315{
5316 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5317 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5318 union iwreq_data wrqu;
5319
5320 ENTER();
5321
5322 switch(pAdapter->device_mode)
5323 {
5324 case WLAN_HDD_INFRA_STATION:
5325 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005326 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005327 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5328 {
5329 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
5330 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5331 pAdapter->sessionId,
5332 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5333 else
5334 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5335 pAdapter->sessionId,
5336 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5337 //success implies disconnect command got queued up successfully
5338 if(halStatus == eHAL_STATUS_SUCCESS)
5339 {
5340 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
5341 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5342 }
5343 memset(&wrqu, '\0', sizeof(wrqu));
5344 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5345 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5346 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
5347 }
5348 else
5349 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305350 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005351 }
5352
5353 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
5354 {
5355 INIT_COMPLETION(pAdapter->session_close_comp_var);
5356 if (eHAL_STATUS_SUCCESS ==
5357 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
5358 hdd_smeCloseSessionCallback, pAdapter))
5359 {
5360 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005361 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005362 &pAdapter->session_close_comp_var,
5363 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5364 }
5365 }
5366
5367 break;
5368
5369 case WLAN_HDD_SOFTAP:
5370 case WLAN_HDD_P2P_GO:
5371 //Any softap specific cleanup here...
5372 mutex_lock(&pHddCtx->sap_lock);
5373 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5374 {
5375 VOS_STATUS status;
5376 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5377
5378 //Stop Bss.
5379 status = WLANSAP_StopBss(pHddCtx->pvosContext);
5380 if (VOS_IS_STATUS_SUCCESS(status))
5381 {
5382 hdd_hostapd_state_t *pHostapdState =
5383 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5384
5385 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
5386
5387 if (!VOS_IS_STATUS_SUCCESS(status))
5388 {
5389 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005390 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005391 }
5392 }
5393 else
5394 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005395 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005396 }
5397 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
5398
5399 if (eHAL_STATUS_FAILURE ==
5400 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5401 0, NULL, eANI_BOOLEAN_FALSE))
5402 {
5403 hddLog(LOGE,
5404 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005405 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005406 }
5407
5408 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
5409 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5410 eANI_BOOLEAN_FALSE) )
5411 {
5412 hddLog(LOGE,
5413 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
5414 }
5415
5416 // Reset WNI_CFG_PROBE_RSP Flags
5417 wlan_hdd_reset_prob_rspies(pAdapter);
5418 kfree(pAdapter->sessionCtx.ap.beacon);
5419 pAdapter->sessionCtx.ap.beacon = NULL;
5420 }
5421 mutex_unlock(&pHddCtx->sap_lock);
5422 break;
5423 case WLAN_HDD_MONITOR:
5424 break;
5425 default:
5426 break;
5427 }
5428
5429 EXIT();
5430 return VOS_STATUS_SUCCESS;
5431}
5432
5433VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
5434{
5435 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5436 VOS_STATUS status;
5437 hdd_adapter_t *pAdapter;
5438
5439 ENTER();
5440
5441 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5442
5443 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5444 {
5445 pAdapter = pAdapterNode->pAdapter;
5446 netif_tx_disable(pAdapter->dev);
5447 netif_carrier_off(pAdapter->dev);
5448
5449 hdd_stop_adapter( pHddCtx, pAdapter );
5450
5451 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5452 pAdapterNode = pNext;
5453 }
5454
5455 EXIT();
5456
5457 return VOS_STATUS_SUCCESS;
5458}
5459
5460VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
5461{
5462 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5463 VOS_STATUS status;
5464 hdd_adapter_t *pAdapter;
5465
5466 ENTER();
5467
5468 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5469
5470 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5471 {
5472 pAdapter = pAdapterNode->pAdapter;
5473 netif_tx_disable(pAdapter->dev);
5474 netif_carrier_off(pAdapter->dev);
5475
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005476 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
5477
Jeff Johnson295189b2012-06-20 16:38:30 -07005478 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305479 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5480 {
5481 hdd_wmm_adapter_close( pAdapter );
5482 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5483 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005484
5485 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5486 pAdapterNode = pNext;
5487 }
5488
5489 EXIT();
5490
5491 return VOS_STATUS_SUCCESS;
5492}
5493
5494VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
5495{
5496 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5497 VOS_STATUS status;
5498 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305499 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07005500
5501 ENTER();
5502
5503 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5504
5505 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5506 {
5507 pAdapter = pAdapterNode->pAdapter;
5508
5509 switch(pAdapter->device_mode)
5510 {
5511 case WLAN_HDD_INFRA_STATION:
5512 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005513 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305514
5515 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
5516
Jeff Johnson295189b2012-06-20 16:38:30 -07005517 hdd_init_station_mode(pAdapter);
5518 /* Open the gates for HDD to receive Wext commands */
5519 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005520 pHddCtx->scan_info.mScanPending = FALSE;
5521 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005522
5523 //Trigger the initial scan
5524 hdd_wlan_initial_scan(pAdapter);
5525
5526 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305527 if (eConnectionState_Associated == connState ||
5528 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07005529 {
5530 union iwreq_data wrqu;
5531 memset(&wrqu, '\0', sizeof(wrqu));
5532 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5533 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5534 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005535 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005536
Jeff Johnson295189b2012-06-20 16:38:30 -07005537 /* indicate disconnected event to nl80211 */
5538 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
5539 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005540 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305541 else if (eConnectionState_Connecting == connState)
5542 {
5543 /*
5544 * Indicate connect failure to supplicant if we were in the
5545 * process of connecting
5546 */
5547 cfg80211_connect_result(pAdapter->dev, NULL,
5548 NULL, 0, NULL, 0,
5549 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
5550 GFP_KERNEL);
5551 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005552 break;
5553
5554 case WLAN_HDD_SOFTAP:
5555 /* softAP can handle SSR */
5556 break;
5557
5558 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07005559 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07005560 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07005561 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005562 break;
5563
5564 case WLAN_HDD_MONITOR:
5565 /* monitor interface start */
5566 break;
5567 default:
5568 break;
5569 }
5570
5571 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5572 pAdapterNode = pNext;
5573 }
5574
5575 EXIT();
5576
5577 return VOS_STATUS_SUCCESS;
5578}
5579
5580VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
5581{
5582 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5583 hdd_adapter_t *pAdapter;
5584 VOS_STATUS status;
5585 v_U32_t roamId;
5586
5587 ENTER();
5588
5589 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5590
5591 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5592 {
5593 pAdapter = pAdapterNode->pAdapter;
5594
5595 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5596 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5597 {
5598 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5599 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5600
5601 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5602 init_completion(&pAdapter->disconnect_comp_var);
5603 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
5604 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5605
5606 wait_for_completion_interruptible_timeout(
5607 &pAdapter->disconnect_comp_var,
5608 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5609
5610 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
5611 pHddCtx->isAmpAllowed = VOS_FALSE;
5612 sme_RoamConnect(pHddCtx->hHal,
5613 pAdapter->sessionId, &(pWextState->roamProfile),
5614 &roamId);
5615 }
5616
5617 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5618 pAdapterNode = pNext;
5619 }
5620
5621 EXIT();
5622
5623 return VOS_STATUS_SUCCESS;
5624}
5625
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07005626void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
5627{
5628 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5629 VOS_STATUS status;
5630 hdd_adapter_t *pAdapter;
5631 hdd_station_ctx_t *pHddStaCtx;
5632 hdd_ap_ctx_t *pHddApCtx;
5633 hdd_hostapd_state_t * pHostapdState;
5634 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
5635 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
5636 const char *p2pMode = "DEV";
5637 const char *ccMode = "Standalone";
5638 int n;
5639
5640 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5641 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5642 {
5643 pAdapter = pAdapterNode->pAdapter;
5644 switch (pAdapter->device_mode) {
5645 case WLAN_HDD_INFRA_STATION:
5646 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5647 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
5648 staChannel = pHddStaCtx->conn_info.operationChannel;
5649 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
5650 }
5651 break;
5652 case WLAN_HDD_P2P_CLIENT:
5653 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5654 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
5655 p2pChannel = pHddStaCtx->conn_info.operationChannel;
5656 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
5657 p2pMode = "CLI";
5658 }
5659 break;
5660 case WLAN_HDD_P2P_GO:
5661 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
5662 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5663 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
5664 p2pChannel = pHddApCtx->operatingChannel;
5665 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
5666 }
5667 p2pMode = "GO";
5668 break;
5669 case WLAN_HDD_SOFTAP:
5670 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
5671 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5672 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
5673 apChannel = pHddApCtx->operatingChannel;
5674 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
5675 }
5676 break;
5677 default:
5678 break;
5679 }
5680 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5681 pAdapterNode = pNext;
5682 }
5683 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
5684 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
5685 }
5686 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
5687 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
5688 if (p2pChannel > 0) {
5689 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
5690 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
5691 }
5692 if (apChannel > 0) {
5693 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
5694 apChannel, MAC_ADDR_ARRAY(apBssid));
5695 }
5696
5697 if (p2pChannel > 0 && apChannel > 0) {
5698 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
5699 }
5700}
5701
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005702bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005703{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005704 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07005705}
5706
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005707/* Once SSR is disabled then it cannot be set. */
5708void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07005709{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005710 if (HDD_SSR_DISABLED == isSsrRequired)
5711 return;
5712
Jeff Johnson295189b2012-06-20 16:38:30 -07005713 isSsrRequired = value;
5714}
5715
5716VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
5717 hdd_adapter_list_node_t** ppAdapterNode)
5718{
5719 VOS_STATUS status;
5720 spin_lock(&pHddCtx->hddAdapters.lock);
5721 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
5722 (hdd_list_node_t**) ppAdapterNode );
5723 spin_unlock(&pHddCtx->hddAdapters.lock);
5724 return status;
5725}
5726
5727VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
5728 hdd_adapter_list_node_t* pAdapterNode,
5729 hdd_adapter_list_node_t** pNextAdapterNode)
5730{
5731 VOS_STATUS status;
5732 spin_lock(&pHddCtx->hddAdapters.lock);
5733 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
5734 (hdd_list_node_t*) pAdapterNode,
5735 (hdd_list_node_t**)pNextAdapterNode );
5736
5737 spin_unlock(&pHddCtx->hddAdapters.lock);
5738 return status;
5739}
5740
5741VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
5742 hdd_adapter_list_node_t* pAdapterNode)
5743{
5744 VOS_STATUS status;
5745 spin_lock(&pHddCtx->hddAdapters.lock);
5746 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
5747 &pAdapterNode->node );
5748 spin_unlock(&pHddCtx->hddAdapters.lock);
5749 return status;
5750}
5751
5752VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
5753 hdd_adapter_list_node_t** ppAdapterNode)
5754{
5755 VOS_STATUS status;
5756 spin_lock(&pHddCtx->hddAdapters.lock);
5757 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
5758 (hdd_list_node_t**) ppAdapterNode );
5759 spin_unlock(&pHddCtx->hddAdapters.lock);
5760 return status;
5761}
5762
5763VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
5764 hdd_adapter_list_node_t* pAdapterNode)
5765{
5766 VOS_STATUS status;
5767 spin_lock(&pHddCtx->hddAdapters.lock);
5768 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
5769 (hdd_list_node_t*) pAdapterNode );
5770 spin_unlock(&pHddCtx->hddAdapters.lock);
5771 return status;
5772}
5773
5774VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
5775 hdd_adapter_list_node_t* pAdapterNode)
5776{
5777 VOS_STATUS status;
5778 spin_lock(&pHddCtx->hddAdapters.lock);
5779 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
5780 (hdd_list_node_t*) pAdapterNode );
5781 spin_unlock(&pHddCtx->hddAdapters.lock);
5782 return status;
5783}
5784
5785hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
5786 tSirMacAddr macAddr )
5787{
5788 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5789 hdd_adapter_t *pAdapter;
5790 VOS_STATUS status;
5791
5792 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5793
5794 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5795 {
5796 pAdapter = pAdapterNode->pAdapter;
5797
5798 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
5799 macAddr, sizeof(tSirMacAddr) ) )
5800 {
5801 return pAdapter;
5802 }
5803 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5804 pAdapterNode = pNext;
5805 }
5806
5807 return NULL;
5808
5809}
5810
5811hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
5812{
5813 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5814 hdd_adapter_t *pAdapter;
5815 VOS_STATUS status;
5816
5817 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5818
5819 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5820 {
5821 pAdapter = pAdapterNode->pAdapter;
5822
5823 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
5824 IFNAMSIZ ) )
5825 {
5826 return pAdapter;
5827 }
5828 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5829 pAdapterNode = pNext;
5830 }
5831
5832 return NULL;
5833
5834}
5835
5836hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
5837{
5838 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5839 hdd_adapter_t *pAdapter;
5840 VOS_STATUS status;
5841
5842 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5843
5844 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5845 {
5846 pAdapter = pAdapterNode->pAdapter;
5847
5848 if( pAdapter && (mode == pAdapter->device_mode) )
5849 {
5850 return pAdapter;
5851 }
5852 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5853 pAdapterNode = pNext;
5854 }
5855
5856 return NULL;
5857
5858}
5859
5860//Remove this function later
5861hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
5862{
5863 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5864 hdd_adapter_t *pAdapter;
5865 VOS_STATUS status;
5866
5867 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5868
5869 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5870 {
5871 pAdapter = pAdapterNode->pAdapter;
5872
5873 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
5874 {
5875 return pAdapter;
5876 }
5877
5878 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5879 pAdapterNode = pNext;
5880 }
5881
5882 return NULL;
5883
5884}
5885
Jeff Johnson295189b2012-06-20 16:38:30 -07005886/**---------------------------------------------------------------------------
5887
5888 \brief hdd_set_monitor_tx_adapter() -
5889
5890 This API initializes the adapter to be used while transmitting on monitor
5891 adapter.
5892
5893 \param - pHddCtx - Pointer to the HDD context.
5894 pAdapter - Adapter that will used for TX. This can be NULL.
5895 \return - None.
5896 --------------------------------------------------------------------------*/
5897void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5898{
5899 hdd_adapter_t *pMonAdapter;
5900
5901 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
5902
5903 if( NULL != pMonAdapter )
5904 {
5905 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
5906 }
5907}
Jeff Johnson295189b2012-06-20 16:38:30 -07005908/**---------------------------------------------------------------------------
5909
5910 \brief hdd_select_queue() -
5911
5912 This API returns the operating channel of the requested device mode
5913
5914 \param - pHddCtx - Pointer to the HDD context.
5915 - mode - Device mode for which operating channel is required
5916 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
5917 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
5918 \return - channel number. "0" id the requested device is not found OR it is not connected.
5919 --------------------------------------------------------------------------*/
5920v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
5921{
5922 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5923 VOS_STATUS status;
5924 hdd_adapter_t *pAdapter;
5925 v_U8_t operatingChannel = 0;
5926
5927 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5928
5929 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5930 {
5931 pAdapter = pAdapterNode->pAdapter;
5932
5933 if( mode == pAdapter->device_mode )
5934 {
5935 switch(pAdapter->device_mode)
5936 {
5937 case WLAN_HDD_INFRA_STATION:
5938 case WLAN_HDD_P2P_CLIENT:
5939 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5940 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
5941 break;
5942 case WLAN_HDD_SOFTAP:
5943 case WLAN_HDD_P2P_GO:
5944 /*softap connection info */
5945 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5946 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
5947 break;
5948 default:
5949 break;
5950 }
5951
5952 break; //Found the device of interest. break the loop
5953 }
5954
5955 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5956 pAdapterNode = pNext;
5957 }
5958 return operatingChannel;
5959}
5960
5961#ifdef WLAN_FEATURE_PACKET_FILTERING
5962/**---------------------------------------------------------------------------
5963
5964 \brief hdd_set_multicast_list() -
5965
5966 This used to set the multicast address list.
5967
5968 \param - dev - Pointer to the WLAN device.
5969 - skb - Pointer to OS packet (sk_buff).
5970 \return - success/fail
5971
5972 --------------------------------------------------------------------------*/
5973static void hdd_set_multicast_list(struct net_device *dev)
5974{
5975 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005976 int mc_count;
5977 int i = 0;
5978 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05305979
5980 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07005981 {
5982 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05305983 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005984 return;
5985 }
5986
5987 if (dev->flags & IFF_ALLMULTI)
5988 {
5989 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005990 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05305991 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005992 }
5993 else
5994 {
5995 mc_count = netdev_mc_count(dev);
5996 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005997 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07005998 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
5999 {
6000 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006001 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306002 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006003 return;
6004 }
6005
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306006 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006007
6008 netdev_for_each_mc_addr(ha, dev) {
6009 if (i == mc_count)
6010 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306011 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6012 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6013 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006014 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306015 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006016 i++;
6017 }
6018 }
6019 return;
6020}
6021#endif
6022
6023/**---------------------------------------------------------------------------
6024
6025 \brief hdd_select_queue() -
6026
6027 This function is registered with the Linux OS for network
6028 core to decide which queue to use first.
6029
6030 \param - dev - Pointer to the WLAN device.
6031 - skb - Pointer to OS packet (sk_buff).
6032 \return - ac, Queue Index/access category corresponding to UP in IP header
6033
6034 --------------------------------------------------------------------------*/
6035v_U16_t hdd_select_queue(struct net_device *dev,
6036 struct sk_buff *skb)
6037{
6038 return hdd_wmm_select_queue(dev, skb);
6039}
6040
6041
6042/**---------------------------------------------------------------------------
6043
6044 \brief hdd_wlan_initial_scan() -
6045
6046 This function triggers the initial scan
6047
6048 \param - pAdapter - Pointer to the HDD adapter.
6049
6050 --------------------------------------------------------------------------*/
6051void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6052{
6053 tCsrScanRequest scanReq;
6054 tCsrChannelInfo channelInfo;
6055 eHalStatus halStatus;
6056 unsigned long scanId;
6057 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6058
6059 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6060 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6061 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6062
6063 if(sme_Is11dSupported(pHddCtx->hHal))
6064 {
6065 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6066 if ( HAL_STATUS_SUCCESS( halStatus ) )
6067 {
6068 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6069 if( !scanReq.ChannelInfo.ChannelList )
6070 {
6071 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6072 vos_mem_free(channelInfo.ChannelList);
6073 return;
6074 }
6075 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6076 channelInfo.numOfChannels);
6077 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6078 vos_mem_free(channelInfo.ChannelList);
6079 }
6080
6081 scanReq.scanType = eSIR_PASSIVE_SCAN;
6082 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6083 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6084 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6085 }
6086 else
6087 {
6088 scanReq.scanType = eSIR_ACTIVE_SCAN;
6089 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6090 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6091 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6092 }
6093
6094 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6095 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6096 {
6097 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6098 __func__, halStatus );
6099 }
6100
6101 if(sme_Is11dSupported(pHddCtx->hHal))
6102 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6103}
6104
6105struct fullPowerContext
6106{
6107 struct completion completion;
6108 unsigned int magic;
6109};
6110#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6111
6112/**---------------------------------------------------------------------------
6113
6114 \brief hdd_full_power_callback() - HDD full power callback function
6115
6116 This is the function invoked by SME to inform the result of a full power
6117 request issued by HDD
6118
6119 \param - callbackcontext - Pointer to cookie
6120 \param - status - result of request
6121
6122 \return - None
6123
6124 --------------------------------------------------------------------------*/
6125static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6126{
6127 struct fullPowerContext *pContext = callbackContext;
6128
6129 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306130 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006131
6132 if (NULL == callbackContext)
6133 {
6134 hddLog(VOS_TRACE_LEVEL_ERROR,
6135 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006136 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006137 return;
6138 }
6139
6140 /* there is a race condition that exists between this callback function
6141 and the caller since the caller could time out either before or
6142 while this code is executing. we'll assume the timeout hasn't
6143 occurred, but we'll verify that right before we save our work */
6144
6145 if (POWER_CONTEXT_MAGIC != pContext->magic)
6146 {
6147 /* the caller presumably timed out so there is nothing we can do */
6148 hddLog(VOS_TRACE_LEVEL_WARN,
6149 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006150 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006151 return;
6152 }
6153
6154 /* the race is on. caller could have timed out immediately after
6155 we verified the magic, but if so, caller will wait a short time
6156 for us to notify the caller, so the context will stay valid */
6157 complete(&pContext->completion);
6158}
6159
6160/**---------------------------------------------------------------------------
6161
6162 \brief hdd_wlan_exit() - HDD WLAN exit function
6163
6164 This is the driver exit point (invoked during rmmod)
6165
6166 \param - pHddCtx - Pointer to the HDD Context
6167
6168 \return - None
6169
6170 --------------------------------------------------------------------------*/
6171void hdd_wlan_exit(hdd_context_t *pHddCtx)
6172{
6173 eHalStatus halStatus;
6174 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6175 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306176 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006177 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006178 struct fullPowerContext powerContext;
6179 long lrc;
6180
6181 ENTER();
6182
Jeff Johnson88ba7742013-02-27 14:36:02 -08006183 if (VOS_FTM_MODE != hdd_get_conparam())
6184 {
6185 // Unloading, restart logic is no more required.
6186 wlan_hdd_restart_deinit(pHddCtx);
6187 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006188
Jeff Johnson295189b2012-06-20 16:38:30 -07006189 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006190 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006192 {
6193 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6194 WLAN_HDD_INFRA_STATION);
6195 if (pAdapter == NULL)
6196 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6197
6198 if (pAdapter != NULL)
6199 {
6200 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6201 hdd_UnregisterWext(pAdapter->dev);
6202 }
6203 }
6204 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006205
Jeff Johnson295189b2012-06-20 16:38:30 -07006206 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006207 {
6208 wlan_hdd_ftm_close(pHddCtx);
6209 goto free_hdd_ctx;
6210 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006211 //Stop the Interface TX queue.
6212 //netif_tx_disable(pWlanDev);
6213 //netif_carrier_off(pWlanDev);
6214
Jeff Johnson295189b2012-06-20 16:38:30 -07006215 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6216 {
6217 pAdapter = hdd_get_adapter(pHddCtx,
6218 WLAN_HDD_SOFTAP);
6219 }
6220 else
6221 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006222 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006223 {
6224 pAdapter = hdd_get_adapter(pHddCtx,
6225 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006226 if (pAdapter == NULL)
6227 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006228 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006229 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006230 /* DeRegister with platform driver as client for Suspend/Resume */
6231 vosStatus = hddDeregisterPmOps(pHddCtx);
6232 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6233 {
6234 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6235 VOS_ASSERT(0);
6236 }
6237
6238 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6239 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6240 {
6241 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6242 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006243
6244 // Cancel any outstanding scan requests. We are about to close all
6245 // of our adapters, but an adapter structure is what SME passes back
6246 // to our callback function. Hence if there are any outstanding scan
6247 // requests then there is a race condition between when the adapter
6248 // is closed and when the callback is invoked. We try to resolve that
6249 // race condition here by canceling any outstanding scans before we
6250 // close the adapters.
6251 // Note that the scans may be cancelled in an asynchronous manner, so
6252 // ideally there needs to be some kind of synchronization. Rather than
6253 // introduce a new synchronization here, we will utilize the fact that
6254 // we are about to Request Full Power, and since that is synchronized,
6255 // the expectation is that by the time Request Full Power has completed,
6256 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006257 if (NULL != pAdapter)
6258 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6259 else
6260 hddLog(VOS_TRACE_LEVEL_ERROR,
6261 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006262
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006263 //Stop the traffic monitor timer
6264 if ( VOS_TIMER_STATE_RUNNING ==
6265 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6266 {
6267 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6268 }
6269
6270 // Destroy the traffic monitor timer
6271 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
6272 &pHddCtx->tx_rx_trafficTmr)))
6273 {
6274 hddLog(VOS_TRACE_LEVEL_ERROR,
6275 "%s: Cannot deallocate Traffic monitor timer", __func__);
6276 }
6277
Jeff Johnson295189b2012-06-20 16:38:30 -07006278 //Disable IMPS/BMPS as we do not want the device to enter any power
6279 //save mode during shutdown
6280 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6281 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6282 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
6283
6284 //Ensure that device is in full power as we will touch H/W during vos_Stop
6285 init_completion(&powerContext.completion);
6286 powerContext.magic = POWER_CONTEXT_MAGIC;
6287
6288 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
6289 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
6290
6291 if (eHAL_STATUS_SUCCESS != halStatus)
6292 {
6293 if (eHAL_STATUS_PMC_PENDING == halStatus)
6294 {
6295 /* request was sent -- wait for the response */
6296 lrc = wait_for_completion_interruptible_timeout(
6297 &powerContext.completion,
6298 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
6299 /* either we have a response or we timed out
6300 either way, first invalidate our magic */
6301 powerContext.magic = 0;
6302 if (lrc <= 0)
6303 {
6304 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006305 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07006306 /* there is a race condition such that the callback
6307 function could be executing at the same time we are. of
6308 primary concern is if the callback function had already
6309 verified the "magic" but hasn't yet set the completion
6310 variable. Since the completion variable is on our
6311 stack, we'll delay just a bit to make sure the data is
6312 still valid if that is the case */
6313 msleep(50);
6314 }
6315 }
6316 else
6317 {
6318 hddLog(VOS_TRACE_LEVEL_ERROR,
6319 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006320 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07006321 VOS_ASSERT(0);
6322 /* continue -- need to clean up as much as possible */
6323 }
6324 }
6325
Yue Ma0d4891e2013-08-06 17:01:45 -07006326 hdd_debugfs_exit(pHddCtx);
6327
Jeff Johnson295189b2012-06-20 16:38:30 -07006328 // Unregister the Net Device Notifier
6329 unregister_netdevice_notifier(&hdd_netdev_notifier);
6330
Jeff Johnson295189b2012-06-20 16:38:30 -07006331 hdd_stop_all_adapters( pHddCtx );
6332
Jeff Johnson295189b2012-06-20 16:38:30 -07006333#ifdef WLAN_BTAMP_FEATURE
6334 vosStatus = WLANBAP_Stop(pVosContext);
6335 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6336 {
6337 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
6338 "%s: Failed to stop BAP",__func__);
6339 }
6340#endif //WLAN_BTAMP_FEATURE
6341
6342 //Stop all the modules
6343 vosStatus = vos_stop( pVosContext );
6344 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6345 {
6346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6347 "%s: Failed to stop VOSS",__func__);
6348 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6349 }
6350
Jeff Johnson295189b2012-06-20 16:38:30 -07006351 //Assert Deep sleep signal now to put Libra HW in lowest power state
6352 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6353 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6354
6355 //Vote off any PMIC voltage supplies
6356 vos_chipPowerDown(NULL, NULL, NULL);
6357
6358 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
6359
Leo Chang59cdc7e2013-07-10 10:08:21 -07006360
Jeff Johnson295189b2012-06-20 16:38:30 -07006361 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07006362 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006363
6364 //Close the scheduler before calling vos_close to make sure no thread is
6365 // scheduled after the each module close is called i.e after all the data
6366 // structures are freed.
6367 vosStatus = vos_sched_close( pVosContext );
6368 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
6369 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6370 "%s: Failed to close VOSS Scheduler",__func__);
6371 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6372 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006373#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006374#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6375 /* Destroy the wake lock */
6376 wake_lock_destroy(&pHddCtx->rx_wake_lock);
6377#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006378 /* Destroy the wake lock */
6379 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006380#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006381
6382 //Close VOSS
6383 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
6384 vos_close(pVosContext);
6385
Jeff Johnson295189b2012-06-20 16:38:30 -07006386 //Close Watchdog
6387 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6388 vos_watchdog_close(pVosContext);
6389
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306390 //Clean up HDD Nlink Service
6391 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07006392#ifdef WLAN_KD_READY_NOTIFIER
6393 nl_srv_exit(pHddCtx->ptt_pid);
6394#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306395 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006396#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306397
Jeff Johnson295189b2012-06-20 16:38:30 -07006398 /* Cancel the vote for XO Core ON.
6399 * This is done here to ensure there is no race condition since MC, TX and WD threads have
6400 * exited at this point
6401 */
6402 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
6403 " when WLAN is turned OFF\n");
6404 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6405 {
6406 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
6407 " Not returning failure."
6408 " Power consumed will be high\n");
6409 }
6410
6411 hdd_close_all_adapters( pHddCtx );
6412
6413
6414 //Free up dynamically allocated members inside HDD Adapter
6415 kfree(pHddCtx->cfg_ini);
6416 pHddCtx->cfg_ini= NULL;
6417
6418 /* free the power on lock from platform driver */
6419 if (free_riva_power_on_lock("wlan"))
6420 {
6421 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
6422 __func__);
6423 }
6424
Jeff Johnson88ba7742013-02-27 14:36:02 -08006425free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07006426 /* FTM mode, WIPHY did not registered
6427 If un-register here, system crash will happen */
6428 if (VOS_FTM_MODE != hdd_get_conparam())
6429 {
6430 wiphy_unregister(wiphy) ;
6431 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006432 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006433 if (hdd_is_ssr_required())
6434 {
6435 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07006436 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07006437 msleep(5000);
6438 }
6439 hdd_set_ssr_required (VOS_FALSE);
6440}
6441
6442
6443/**---------------------------------------------------------------------------
6444
6445 \brief hdd_update_config_from_nv() - Function to update the contents of
6446 the running configuration with parameters taken from NV storage
6447
6448 \param - pHddCtx - Pointer to the HDD global context
6449
6450 \return - VOS_STATUS_SUCCESS if successful
6451
6452 --------------------------------------------------------------------------*/
6453static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
6454{
Jeff Johnson295189b2012-06-20 16:38:30 -07006455 v_BOOL_t itemIsValid = VOS_FALSE;
6456 VOS_STATUS status;
6457 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
6458 v_U8_t macLoop;
6459
6460 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
6461 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
6462 if(status != VOS_STATUS_SUCCESS)
6463 {
6464 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
6465 return VOS_STATUS_E_FAILURE;
6466 }
6467
6468 if (itemIsValid == VOS_TRUE)
6469 {
6470 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
6471 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
6472 VOS_MAX_CONCURRENCY_PERSONA);
6473 if(status != VOS_STATUS_SUCCESS)
6474 {
6475 /* Get MAC from NV fail, not update CFG info
6476 * INI MAC value will be used for MAC setting */
6477 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
6478 return VOS_STATUS_E_FAILURE;
6479 }
6480
6481 /* If first MAC is not valid, treat all others are not valid
6482 * Then all MACs will be got from ini file */
6483 if(vos_is_macaddr_zero(&macFromNV[0]))
6484 {
6485 /* MAC address in NV file is not configured yet */
6486 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
6487 return VOS_STATUS_E_INVAL;
6488 }
6489
6490 /* Get MAC address from NV, update CFG info */
6491 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
6492 {
6493 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
6494 {
6495 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
6496 /* This MAC is not valid, skip it
6497 * This MAC will be got from ini file */
6498 }
6499 else
6500 {
6501 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
6502 (v_U8_t *)&macFromNV[macLoop].bytes[0],
6503 VOS_MAC_ADDR_SIZE);
6504 }
6505 }
6506 }
6507 else
6508 {
6509 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
6510 return VOS_STATUS_E_FAILURE;
6511 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006512
Jeff Johnson295189b2012-06-20 16:38:30 -07006513
6514 return VOS_STATUS_SUCCESS;
6515}
6516
6517/**---------------------------------------------------------------------------
6518
6519 \brief hdd_post_voss_start_config() - HDD post voss start config helper
6520
6521 \param - pAdapter - Pointer to the HDD
6522
6523 \return - None
6524
6525 --------------------------------------------------------------------------*/
6526VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
6527{
6528 eHalStatus halStatus;
6529 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306530 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07006531
Jeff Johnson295189b2012-06-20 16:38:30 -07006532
6533 // Send ready indication to the HDD. This will kick off the MAC
6534 // into a 'running' state and should kick off an initial scan.
6535 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
6536 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6537 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306538 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07006539 "code %08d [x%08x]",__func__, halStatus, halStatus );
6540 return VOS_STATUS_E_FAILURE;
6541 }
6542
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306543 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07006544 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
6545 // And RIVA will crash
6546 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
6547 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306548 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
6549 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
6550
6551
Jeff Johnson295189b2012-06-20 16:38:30 -07006552 return VOS_STATUS_SUCCESS;
6553}
6554
Jeff Johnson295189b2012-06-20 16:38:30 -07006555/* wake lock APIs for HDD */
6556void hdd_prevent_suspend(void)
6557{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006558#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006559 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006560#else
6561 wcnss_prevent_suspend();
6562#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006563}
6564
6565void hdd_allow_suspend(void)
6566{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006567#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006568 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006569#else
6570 wcnss_allow_suspend();
6571#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006572}
6573
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07006574void hdd_allow_suspend_timeout(v_U32_t timeout)
6575{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006576#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07006577 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07006578#else
6579 /* Do nothing as there is no API in wcnss for timeout*/
6580#endif
6581}
6582
Jeff Johnson295189b2012-06-20 16:38:30 -07006583/**---------------------------------------------------------------------------
6584
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006585 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
6586 information between Host and Riva
6587
6588 This function gets reported version of FW
6589 It also finds the version of Riva headers used to compile the host
6590 It compares the above two and prints a warning if they are different
6591 It gets the SW and HW version string
6592 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
6593 indicating the features they support through a bitmap
6594
6595 \param - pHddCtx - Pointer to HDD context
6596
6597 \return - void
6598
6599 --------------------------------------------------------------------------*/
6600
6601void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
6602{
6603
6604 tSirVersionType versionCompiled;
6605 tSirVersionType versionReported;
6606 tSirVersionString versionString;
6607 tANI_U8 fwFeatCapsMsgSupported = 0;
6608 VOS_STATUS vstatus;
6609
6610 /* retrieve and display WCNSS version information */
6611 do {
6612
6613 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
6614 &versionCompiled);
6615 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6616 {
6617 hddLog(VOS_TRACE_LEVEL_FATAL,
6618 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006619 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006620 break;
6621 }
6622
6623 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
6624 &versionReported);
6625 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6626 {
6627 hddLog(VOS_TRACE_LEVEL_FATAL,
6628 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006629 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006630 break;
6631 }
6632
6633 if ((versionCompiled.major != versionReported.major) ||
6634 (versionCompiled.minor != versionReported.minor) ||
6635 (versionCompiled.version != versionReported.version) ||
6636 (versionCompiled.revision != versionReported.revision))
6637 {
6638 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
6639 "Host expected %u.%u.%u.%u\n",
6640 WLAN_MODULE_NAME,
6641 (int)versionReported.major,
6642 (int)versionReported.minor,
6643 (int)versionReported.version,
6644 (int)versionReported.revision,
6645 (int)versionCompiled.major,
6646 (int)versionCompiled.minor,
6647 (int)versionCompiled.version,
6648 (int)versionCompiled.revision);
6649 }
6650 else
6651 {
6652 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
6653 WLAN_MODULE_NAME,
6654 (int)versionReported.major,
6655 (int)versionReported.minor,
6656 (int)versionReported.version,
6657 (int)versionReported.revision);
6658 }
6659
6660 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
6661 versionString,
6662 sizeof(versionString));
6663 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6664 {
6665 hddLog(VOS_TRACE_LEVEL_FATAL,
6666 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006667 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006668 break;
6669 }
6670
6671 pr_info("%s: WCNSS software version %s\n",
6672 WLAN_MODULE_NAME, versionString);
6673
6674 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
6675 versionString,
6676 sizeof(versionString));
6677 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6678 {
6679 hddLog(VOS_TRACE_LEVEL_FATAL,
6680 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006681 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006682 break;
6683 }
6684
6685 pr_info("%s: WCNSS hardware version %s\n",
6686 WLAN_MODULE_NAME, versionString);
6687
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006688 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
6689 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006690 send the message only if it the riva is 1.1
6691 minor numbers for different riva branches:
6692 0 -> (1.0)Mainline Build
6693 1 -> (1.1)Mainline Build
6694 2->(1.04) Stability Build
6695 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006696 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006697 ((versionReported.minor>=1) && (versionReported.version>=1)))
6698 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
6699 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006700
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006701 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08006702 {
6703#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6704 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
6705 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
6706#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07006707 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
6708 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
6709 {
6710 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
6711 }
6712
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006713 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08006714 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006715
6716 } while (0);
6717
6718}
6719
6720/**---------------------------------------------------------------------------
6721
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05306722 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
6723
6724 \param - pHddCtx - Pointer to the hdd context
6725
6726 \return - true if hardware supports 5GHz
6727
6728 --------------------------------------------------------------------------*/
6729static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
6730{
6731 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
6732 * then hardware support 5Ghz.
6733 */
6734 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
6735 {
6736 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
6737 return true;
6738 }
6739 else
6740 {
6741 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
6742 __func__);
6743 return false;
6744 }
6745}
6746
6747
6748/**---------------------------------------------------------------------------
6749
Jeff Johnson295189b2012-06-20 16:38:30 -07006750 \brief hdd_wlan_startup() - HDD init function
6751
6752 This is the driver startup code executed once a WLAN device has been detected
6753
6754 \param - dev - Pointer to the underlying device
6755
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006756 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07006757
6758 --------------------------------------------------------------------------*/
6759
6760int hdd_wlan_startup(struct device *dev )
6761{
6762 VOS_STATUS status;
6763 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07006764 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006765 hdd_context_t *pHddCtx = NULL;
6766 v_CONTEXT_t pVosContext= NULL;
6767#ifdef WLAN_BTAMP_FEATURE
6768 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
6769 WLANBAP_ConfigType btAmpConfig;
6770 hdd_config_t *pConfig;
6771#endif
6772 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006773 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006774
6775 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006776 /*
6777 * cfg80211: wiphy allocation
6778 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306779 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006780
6781 if(wiphy == NULL)
6782 {
6783 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006784 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006785 }
6786
6787 pHddCtx = wiphy_priv(wiphy);
6788
Jeff Johnson295189b2012-06-20 16:38:30 -07006789 //Initialize the adapter context to zeros.
6790 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
6791
Jeff Johnson295189b2012-06-20 16:38:30 -07006792 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006793 hdd_prevent_suspend();
6794 pHddCtx->isLoadUnloadInProgress = TRUE;
6795
6796 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6797
6798 /*Get vos context here bcoz vos_open requires it*/
6799 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6800
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08006801 if(pVosContext == NULL)
6802 {
6803 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
6804 goto err_free_hdd_context;
6805 }
6806
Jeff Johnson295189b2012-06-20 16:38:30 -07006807 //Save the Global VOSS context in adapter context for future.
6808 pHddCtx->pvosContext = pVosContext;
6809
6810 //Save the adapter context in global context for future.
6811 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
6812
Jeff Johnson295189b2012-06-20 16:38:30 -07006813 pHddCtx->parent_dev = dev;
6814
6815 init_completion(&pHddCtx->full_pwr_comp_var);
6816 init_completion(&pHddCtx->standby_comp_var);
6817 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006818 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08006819 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07006820
6821#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07006822 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07006823#else
6824 init_completion(&pHddCtx->driver_crda_req);
6825#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006826
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05306827 spin_lock_init(&pHddCtx->schedScan_lock);
6828
Jeff Johnson295189b2012-06-20 16:38:30 -07006829 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
6830
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306831#ifdef FEATURE_WLAN_TDLS
6832 /* tdls_lock is initialized before an hdd_open_adapter ( which is
6833 * invoked by other instances also) to protect the concurrent
6834 * access for the Adapters by TDLS module.
6835 */
6836 mutex_init(&pHddCtx->tdls_lock);
6837#endif
6838
Jeff Johnson295189b2012-06-20 16:38:30 -07006839 // Load all config first as TL config is needed during vos_open
6840 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
6841 if(pHddCtx->cfg_ini == NULL)
6842 {
6843 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
6844 goto err_free_hdd_context;
6845 }
6846
6847 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
6848
6849 // Read and parse the qcom_cfg.ini file
6850 status = hdd_parse_config_ini( pHddCtx );
6851 if ( VOS_STATUS_SUCCESS != status )
6852 {
6853 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
6854 __func__, WLAN_INI_FILE);
6855 goto err_config;
6856 }
6857
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05306858 /* INI has been read, initialise the configuredMcastBcastFilter with
6859 * INI value as this will serve as the default value
6860 */
6861 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
6862 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
6863 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05306864
6865 if (false == hdd_is_5g_supported(pHddCtx))
6866 {
6867 //5Ghz is not supported.
6868 if (1 != pHddCtx->cfg_ini->nBandCapability)
6869 {
6870 hddLog(VOS_TRACE_LEVEL_INFO,
6871 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
6872 pHddCtx->cfg_ini->nBandCapability = 1;
6873 }
6874 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05306875
6876 /* If SNR Monitoring is enabled, FW has to parse all beacons
6877 * for calcaluting and storing the average SNR, so set Nth beacon
6878 * filter to 1 to enable FW to parse all the beaocons
6879 */
6880 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
6881 {
6882 /* The log level is deliberately set to WARN as overriding
6883 * nthBeaconFilter to 1 will increase power cosumption and this
6884 * might just prove helpful to detect the power issue.
6885 */
6886 hddLog(VOS_TRACE_LEVEL_WARN,
6887 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
6888 pHddCtx->cfg_ini->nthBeaconFilter = 1;
6889 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006890 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306891 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07006892 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306893 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07006894 {
6895 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306896 "%s: wlan_hdd_cfg80211_init return failure", __func__);
6897 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07006898 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006899
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006900 // Update VOS trace levels based upon the cfg.ini
6901 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
6902 pHddCtx->cfg_ini->vosTraceEnableBAP);
6903 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
6904 pHddCtx->cfg_ini->vosTraceEnableTL);
6905 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
6906 pHddCtx->cfg_ini->vosTraceEnableWDI);
6907 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
6908 pHddCtx->cfg_ini->vosTraceEnableHDD);
6909 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
6910 pHddCtx->cfg_ini->vosTraceEnableSME);
6911 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
6912 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05306913 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
6914 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006915 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
6916 pHddCtx->cfg_ini->vosTraceEnableWDA);
6917 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
6918 pHddCtx->cfg_ini->vosTraceEnableSYS);
6919 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
6920 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006921 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
6922 pHddCtx->cfg_ini->vosTraceEnableSAP);
6923 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
6924 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006925
Jeff Johnson295189b2012-06-20 16:38:30 -07006926 // Update WDI trace levels based upon the cfg.ini
6927 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
6928 pHddCtx->cfg_ini->wdiTraceEnableDAL);
6929 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
6930 pHddCtx->cfg_ini->wdiTraceEnableCTL);
6931 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
6932 pHddCtx->cfg_ini->wdiTraceEnableDAT);
6933 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
6934 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006935
Jeff Johnson88ba7742013-02-27 14:36:02 -08006936 if (VOS_FTM_MODE == hdd_get_conparam())
6937 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006938 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
6939 {
6940 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
6941 goto err_free_hdd_context;
6942 }
6943 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
6944 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08006945 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006946
Jeff Johnson88ba7742013-02-27 14:36:02 -08006947 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07006948 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6949 {
6950 status = vos_watchdog_open(pVosContext,
6951 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
6952
6953 if(!VOS_IS_STATUS_SUCCESS( status ))
6954 {
6955 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306956 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07006957 }
6958 }
6959
6960 pHddCtx->isLogpInProgress = FALSE;
6961 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
6962
Jeff Johnson295189b2012-06-20 16:38:30 -07006963 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
6964 if(!VOS_IS_STATUS_SUCCESS(status))
6965 {
6966 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006967 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07006968 }
6969
Amar Singhala49cbc52013-10-08 18:37:44 -07006970#ifdef CONFIG_ENABLE_LINUX_REG
6971 /* registration of wiphy dev with cfg80211 */
6972 if (0 > wlan_hdd_cfg80211_register(wiphy))
6973 {
6974 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
6975 goto err_clkvote;
6976 }
6977#endif
6978
Jeff Johnson295189b2012-06-20 16:38:30 -07006979 status = vos_open( &pVosContext, 0);
6980 if ( !VOS_IS_STATUS_SUCCESS( status ))
6981 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006982 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07006983 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07006984 }
6985
Jeff Johnson295189b2012-06-20 16:38:30 -07006986 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
6987
6988 if ( NULL == pHddCtx->hHal )
6989 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006990 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006991 goto err_vosclose;
6992 }
6993
Jeff Johnsonbc676b42013-02-14 16:04:08 -08006994 status = vos_preStart( pHddCtx->pvosContext );
6995 if ( !VOS_IS_STATUS_SUCCESS( status ) )
6996 {
6997 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
6998 goto err_vosclose;
6999 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007000
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007001 /* Note that the vos_preStart() sequence triggers the cfg download.
7002 The cfg download must occur before we update the SME config
7003 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007004 status = hdd_set_sme_config( pHddCtx );
7005
7006 if ( VOS_STATUS_SUCCESS != status )
7007 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007008 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7009 goto err_vosclose;
7010 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007011
7012 //Initialize the WMM module
7013 status = hdd_wmm_init(pHddCtx);
7014 if (!VOS_IS_STATUS_SUCCESS(status))
7015 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007016 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007017 goto err_vosclose;
7018 }
7019
Jeff Johnson295189b2012-06-20 16:38:30 -07007020 /* In the integrated architecture we update the configuration from
7021 the INI file and from NV before vOSS has been started so that
7022 the final contents are available to send down to the cCPU */
7023
7024 // Apply the cfg.ini to cfg.dat
7025 if (FALSE == hdd_update_config_dat(pHddCtx))
7026 {
7027 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7028 goto err_vosclose;
7029 }
7030
7031 // Apply the NV to cfg.dat
7032 /* Prima Update MAC address only at here */
7033 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7034 {
7035#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7036 /* There was not a valid set of MAC Addresses in NV. See if the
7037 default addresses were modified by the cfg.ini settings. If so,
7038 we'll use them, but if not, we'll autogenerate a set of MAC
7039 addresses based upon the device serial number */
7040
7041 static const v_MACADDR_t default_address =
7042 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7043 unsigned int serialno;
7044 int i;
7045
7046 serialno = wcnss_get_serial_number();
7047 if ((0 != serialno) &&
7048 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7049 sizeof(default_address))))
7050 {
7051 /* cfg.ini has the default address, invoke autogen logic */
7052
7053 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7054 bytes of the serial number that can be used to generate
7055 the other 3 bytes of the MAC address. Mask off all but
7056 the lower 3 bytes (this will also make sure we don't
7057 overflow in the next step) */
7058 serialno &= 0x00FFFFFF;
7059
7060 /* we need a unique address for each session */
7061 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7062
7063 /* autogen all addresses */
7064 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7065 {
7066 /* start with the entire default address */
7067 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7068 /* then replace the lower 3 bytes */
7069 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7070 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7071 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7072
7073 serialno++;
7074 }
7075
7076 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7077 MAC_ADDRESS_STR,
7078 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7079 }
7080 else
7081#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7082 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007083 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007084 "%s: Invalid MAC address in NV, using MAC from ini file "
7085 MAC_ADDRESS_STR, __func__,
7086 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7087 }
7088 }
7089 {
7090 eHalStatus halStatus;
7091 // Set the MAC Address
7092 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7093 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7094 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7095 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7096
7097 if (!HAL_STATUS_SUCCESS( halStatus ))
7098 {
7099 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7100 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007101 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007102 }
7103 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007104
7105 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7106 Note: Firmware image will be read and downloaded inside vos_start API */
7107 status = vos_start( pHddCtx->pvosContext );
7108 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7109 {
7110 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7111 goto err_vosclose;
7112 }
7113
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007114 /* Exchange capability info between Host and FW and also get versioning info from FW */
7115 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007116
7117 status = hdd_post_voss_start_config( pHddCtx );
7118 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7119 {
7120 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7121 __func__);
7122 goto err_vosstop;
7123 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007124
7125#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307126 wlan_hdd_cfg80211_update_reg_info( wiphy );
7127
7128 /* registration of wiphy dev with cfg80211 */
7129 if (0 > wlan_hdd_cfg80211_register(wiphy))
7130 {
7131 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7132 goto err_vosstop;
7133 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007134#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007135
Jeff Johnson295189b2012-06-20 16:38:30 -07007136 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7137 {
7138 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7139 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7140 }
7141 else
7142 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007143 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7144 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7145 if (pAdapter != NULL)
7146 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307147 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007148 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307149 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7150 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7151 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007152
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307153 /* Generate the P2P Device Address. This consists of the device's
7154 * primary MAC address with the locally administered bit set.
7155 */
7156 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007157 }
7158 else
7159 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307160 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7161 if (p2p_dev_addr != NULL)
7162 {
7163 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7164 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7165 }
7166 else
7167 {
7168 hddLog(VOS_TRACE_LEVEL_FATAL,
7169 "%s: Failed to allocate mac_address for p2p_device",
7170 __func__);
7171 goto err_close_adapter;
7172 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007173 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007174
7175 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7176 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7177 if ( NULL == pP2pAdapter )
7178 {
7179 hddLog(VOS_TRACE_LEVEL_FATAL,
7180 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007181 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007182 goto err_close_adapter;
7183 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007184 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007185 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007186
7187 if( pAdapter == NULL )
7188 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007189 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7190 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007191 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007192
Jeff Johnson295189b2012-06-20 16:38:30 -07007193#ifdef WLAN_BTAMP_FEATURE
7194 vStatus = WLANBAP_Open(pVosContext);
7195 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7196 {
7197 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7198 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007199 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007200 }
7201
7202 vStatus = BSL_Init(pVosContext);
7203 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7204 {
7205 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7206 "%s: Failed to Init BSL",__func__);
7207 goto err_bap_close;
7208 }
7209 vStatus = WLANBAP_Start(pVosContext);
7210 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7211 {
7212 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7213 "%s: Failed to start TL",__func__);
7214 goto err_bap_close;
7215 }
7216
7217 pConfig = pHddCtx->cfg_ini;
7218 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7219 status = WLANBAP_SetConfig(&btAmpConfig);
7220
7221#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007222
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007223#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7224 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7225 {
7226 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7227 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7228 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7229 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7230 }
7231#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007232#ifdef FEATURE_WLAN_SCAN_PNO
7233 /*SME must send channel update configuration to RIVA*/
7234 sme_UpdateChannelConfig(pHddCtx->hHal);
7235#endif
7236
Jeff Johnson295189b2012-06-20 16:38:30 -07007237 /* Register with platform driver as client for Suspend/Resume */
7238 status = hddRegisterPmOps(pHddCtx);
7239 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7240 {
7241 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7242#ifdef WLAN_BTAMP_FEATURE
7243 goto err_bap_stop;
7244#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007245 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007246#endif //WLAN_BTAMP_FEATURE
7247 }
7248
Yue Ma0d4891e2013-08-06 17:01:45 -07007249 /* Open debugfs interface */
7250 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
7251 {
7252 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7253 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07007254 }
7255
Jeff Johnson295189b2012-06-20 16:38:30 -07007256 /* Register TM level change handler function to the platform */
7257 status = hddDevTmRegisterNotifyCallback(pHddCtx);
7258 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7259 {
7260 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
7261 goto err_unregister_pmops;
7262 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007263
7264 /* register for riva power on lock to platform driver */
7265 if (req_riva_power_on_lock("wlan"))
7266 {
7267 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
7268 __func__);
7269 goto err_unregister_pmops;
7270 }
7271
Jeff Johnson295189b2012-06-20 16:38:30 -07007272 // register net device notifier for device change notification
7273 ret = register_netdevice_notifier(&hdd_netdev_notifier);
7274
7275 if(ret < 0)
7276 {
7277 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
7278 goto err_free_power_on_lock;
7279 }
7280
7281 //Initialize the nlink service
7282 if(nl_srv_init() != 0)
7283 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307284 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007285 goto err_reg_netdev;
7286 }
7287
7288 //Initialize the BTC service
7289 if(btc_activate_service(pHddCtx) != 0)
7290 {
7291 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
7292 goto err_nl_srv;
7293 }
7294
7295#ifdef PTT_SOCK_SVC_ENABLE
7296 //Initialize the PTT service
7297 if(ptt_sock_activate_svc(pHddCtx) != 0)
7298 {
7299 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
7300 goto err_nl_srv;
7301 }
7302#endif
7303
Jeff Johnson295189b2012-06-20 16:38:30 -07007304 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007305 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007306 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07007307 /* Action frame registered in one adapter which will
7308 * applicable to all interfaces
7309 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07007310 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007311 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007312
7313 mutex_init(&pHddCtx->sap_lock);
7314
7315 pHddCtx->isLoadUnloadInProgress = FALSE;
7316
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007317#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007318#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7319 /* Initialize the wake lcok */
7320 wake_lock_init(&pHddCtx->rx_wake_lock,
7321 WAKE_LOCK_SUSPEND,
7322 "qcom_rx_wakelock");
7323#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007324 /* Initialize the wake lcok */
7325 wake_lock_init(&pHddCtx->sap_wake_lock,
7326 WAKE_LOCK_SUSPEND,
7327 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007328#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007329
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007330 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
7331 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07007332
7333 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7334 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05307335
Jeff Johnsone7245742012-09-05 17:12:55 -07007336 // Initialize the restart logic
7337 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05307338
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007339 //Register the traffic monitor timer now
7340 if ( pHddCtx->cfg_ini->dynSplitscan)
7341 {
7342 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
7343 VOS_TIMER_TYPE_SW,
7344 hdd_tx_rx_pkt_cnt_stat_timer_handler,
7345 (void *)pHddCtx);
7346 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007347 goto success;
7348
7349err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07007350#ifdef WLAN_KD_READY_NOTIFIER
7351 nl_srv_exit(pHddCtx->ptt_pid);
7352#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007353 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007354#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07007355err_reg_netdev:
7356 unregister_netdevice_notifier(&hdd_netdev_notifier);
7357
7358err_free_power_on_lock:
7359 free_riva_power_on_lock("wlan");
7360
7361err_unregister_pmops:
7362 hddDevTmUnregisterNotifyCallback(pHddCtx);
7363 hddDeregisterPmOps(pHddCtx);
7364
Yue Ma0d4891e2013-08-06 17:01:45 -07007365 hdd_debugfs_exit(pHddCtx);
7366
Jeff Johnson295189b2012-06-20 16:38:30 -07007367#ifdef WLAN_BTAMP_FEATURE
7368err_bap_stop:
7369 WLANBAP_Stop(pVosContext);
7370#endif
7371
7372#ifdef WLAN_BTAMP_FEATURE
7373err_bap_close:
7374 WLANBAP_Close(pVosContext);
7375#endif
7376
Jeff Johnson295189b2012-06-20 16:38:30 -07007377err_close_adapter:
7378 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07007379
7380#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307381 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07007382#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007383
7384err_vosstop:
7385 vos_stop(pVosContext);
7386
Amar Singhala49cbc52013-10-08 18:37:44 -07007387err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07007388 status = vos_sched_close( pVosContext );
7389 if (!VOS_IS_STATUS_SUCCESS(status)) {
7390 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7391 "%s: Failed to close VOSS Scheduler", __func__);
7392 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
7393 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007394 vos_close(pVosContext );
7395
7396err_wiphy_unregister:
7397
7398#ifdef CONFIG_ENABLE_LINUX_REG
7399 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07007400
Jeff Johnson295189b2012-06-20 16:38:30 -07007401err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07007402#endif
7403
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007404 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007405
7406err_wdclose:
7407 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7408 vos_watchdog_close(pVosContext);
7409
Jeff Johnson295189b2012-06-20 16:38:30 -07007410err_config:
7411 kfree(pHddCtx->cfg_ini);
7412 pHddCtx->cfg_ini= NULL;
7413
7414err_free_hdd_context:
7415 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07007416 wiphy_free(wiphy) ;
7417 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007418 VOS_BUG(1);
7419
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08007420 if (hdd_is_ssr_required())
7421 {
7422 /* WDI timeout had happened during load, so SSR is needed here */
7423 subsystem_restart("wcnss");
7424 msleep(5000);
7425 }
7426 hdd_set_ssr_required (VOS_FALSE);
7427
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007428 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007429
7430success:
7431 EXIT();
7432 return 0;
7433}
7434
7435/**---------------------------------------------------------------------------
7436
Jeff Johnson32d95a32012-09-10 13:15:23 -07007437 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07007438
Jeff Johnson32d95a32012-09-10 13:15:23 -07007439 This is the driver entry point - called in different timeline depending
7440 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07007441
7442 \param - None
7443
7444 \return - 0 for success, non zero for failure
7445
7446 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07007447static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007448{
7449 VOS_STATUS status;
7450 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007451 struct device *dev = NULL;
7452 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007453#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7454 int max_retries = 0;
7455#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007456
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307457#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7458 vos_wconn_trace_init();
7459#endif
7460
Jeff Johnson295189b2012-06-20 16:38:30 -07007461 ENTER();
7462
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007463#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007464 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07007465#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007466
7467 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
7468 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
7469
7470 //Power Up Libra WLAN card first if not already powered up
7471 status = vos_chipPowerUp(NULL,NULL,NULL);
7472 if (!VOS_IS_STATUS_SUCCESS(status))
7473 {
7474 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
7475 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307476#ifdef WLAN_OPEN_SOURCE
7477 wake_lock_destroy(&wlan_wake_lock);
7478#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007479 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007480 }
7481
Jeff Johnson295189b2012-06-20 16:38:30 -07007482#ifdef ANI_BUS_TYPE_PCI
7483
7484 dev = wcnss_wlan_get_device();
7485
7486#endif // ANI_BUS_TYPE_PCI
7487
7488#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007489
7490#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7491 /* wait until WCNSS driver downloads NV */
7492 while (!wcnss_device_ready() && 5 >= ++max_retries) {
7493 msleep(1000);
7494 }
7495 if (max_retries >= 5) {
7496 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307497#ifdef WLAN_OPEN_SOURCE
7498 wake_lock_destroy(&wlan_wake_lock);
7499#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007500 return -ENODEV;
7501 }
7502#endif
7503
Jeff Johnson295189b2012-06-20 16:38:30 -07007504 dev = wcnss_wlan_get_device();
7505#endif // ANI_BUS_TYPE_PLATFORM
7506
7507
7508 do {
7509 if (NULL == dev) {
7510 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
7511 ret_status = -1;
7512 break;
7513 }
7514
7515#ifdef MEMORY_DEBUG
7516 vos_mem_init();
7517#endif
7518
7519#ifdef TIMER_MANAGER
7520 vos_timer_manager_init();
7521#endif
7522
7523 /* Preopen VOSS so that it is ready to start at least SAL */
7524 status = vos_preOpen(&pVosContext);
7525
7526 if (!VOS_IS_STATUS_SUCCESS(status))
7527 {
7528 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
7529 ret_status = -1;
7530 break;
7531 }
7532
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007533#ifndef MODULE
7534 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
7535 */
7536 hdd_set_conparam((v_UINT_t)con_mode);
7537#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007538
7539 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007540 if (hdd_wlan_startup(dev))
7541 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007542 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007543 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007544 vos_preClose( &pVosContext );
7545 ret_status = -1;
7546 break;
7547 }
7548
7549 /* Cancel the vote for XO Core ON
7550 * This is done here for safety purposes in case we re-initialize without turning
7551 * it OFF in any error scenario.
7552 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007553 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07007554 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007555 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07007556 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7557 {
7558 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
7559 " Power consumed will be high\n");
7560 }
7561 } while (0);
7562
7563 if (0 != ret_status)
7564 {
7565 //Assert Deep sleep signal now to put Libra HW in lowest power state
7566 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7567 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
7568
7569 //Vote off any PMIC voltage supplies
7570 vos_chipPowerDown(NULL, NULL, NULL);
7571#ifdef TIMER_MANAGER
7572 vos_timer_exit();
7573#endif
7574#ifdef MEMORY_DEBUG
7575 vos_mem_exit();
7576#endif
7577
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007578#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007579 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007580#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007581 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
7582 }
7583 else
7584 {
7585 //Send WLAN UP indication to Nlink Service
7586 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
7587
7588 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07007589 }
7590
7591 EXIT();
7592
7593 return ret_status;
7594}
7595
Jeff Johnson32d95a32012-09-10 13:15:23 -07007596/**---------------------------------------------------------------------------
7597
7598 \brief hdd_module_init() - Init Function
7599
7600 This is the driver entry point (invoked when module is loaded using insmod)
7601
7602 \param - None
7603
7604 \return - 0 for success, non zero for failure
7605
7606 --------------------------------------------------------------------------*/
7607#ifdef MODULE
7608static int __init hdd_module_init ( void)
7609{
7610 return hdd_driver_init();
7611}
Jeff Johnson32d95a32012-09-10 13:15:23 -07007612#else /* #ifdef MODULE */
7613static int __init hdd_module_init ( void)
7614{
7615 /* Driver initialization is delayed to fwpath_changed_handler */
7616 return 0;
7617}
Jeff Johnson32d95a32012-09-10 13:15:23 -07007618#endif /* #ifdef MODULE */
7619
Jeff Johnson295189b2012-06-20 16:38:30 -07007620
7621/**---------------------------------------------------------------------------
7622
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007623 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007624
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007625 This is the driver exit point (invoked when module is unloaded using rmmod
7626 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07007627
7628 \param - None
7629
7630 \return - None
7631
7632 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007633static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007634{
7635 hdd_context_t *pHddCtx = NULL;
7636 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007637 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007638
7639 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
7640
7641 //Get the global vos context
7642 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7643
7644 if(!pVosContext)
7645 {
7646 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
7647 goto done;
7648 }
7649
7650 //Get the HDD context.
7651 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
7652
7653 if(!pHddCtx)
7654 {
7655 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
7656 }
7657 else
7658 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007659 while(isWDresetInProgress()) {
7660 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7661 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007662 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007663
7664 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
7665 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7666 "%s:SSR never completed, fatal error", __func__);
7667 VOS_BUG(0);
7668 }
7669 }
7670
Jeff Johnson295189b2012-06-20 16:38:30 -07007671
7672 pHddCtx->isLoadUnloadInProgress = TRUE;
7673 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7674
7675 //Do all the cleanup before deregistering the driver
7676 hdd_wlan_exit(pHddCtx);
7677 }
7678
Jeff Johnson295189b2012-06-20 16:38:30 -07007679 vos_preClose( &pVosContext );
7680
7681#ifdef TIMER_MANAGER
7682 vos_timer_exit();
7683#endif
7684#ifdef MEMORY_DEBUG
7685 vos_mem_exit();
7686#endif
7687
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307688#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7689 vos_wconn_trace_exit();
7690#endif
7691
Jeff Johnson295189b2012-06-20 16:38:30 -07007692done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007693#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007694 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007695#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007696 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
7697}
7698
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007699/**---------------------------------------------------------------------------
7700
7701 \brief hdd_module_exit() - Exit function
7702
7703 This is the driver exit point (invoked when module is unloaded using rmmod)
7704
7705 \param - None
7706
7707 \return - None
7708
7709 --------------------------------------------------------------------------*/
7710static void __exit hdd_module_exit(void)
7711{
7712 hdd_driver_exit();
7713}
7714
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007715#ifdef MODULE
7716static int fwpath_changed_handler(const char *kmessage,
7717 struct kernel_param *kp)
7718{
Jeff Johnson76052702013-04-16 13:55:05 -07007719 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007720}
7721
7722static int con_mode_handler(const char *kmessage,
7723 struct kernel_param *kp)
7724{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07007725 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007726}
7727#else /* #ifdef MODULE */
7728/**---------------------------------------------------------------------------
7729
Jeff Johnson76052702013-04-16 13:55:05 -07007730 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007731
Jeff Johnson76052702013-04-16 13:55:05 -07007732 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007733 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07007734 - invoked when module parameter fwpath is modified from userspace to signal
7735 initializing the WLAN driver or when con_mode is modified from userspace
7736 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007737
7738 \return - 0 for success, non zero for failure
7739
7740 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07007741static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007742{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007743 int ret_status;
7744
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007745 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007746 ret_status = hdd_driver_init();
7747 wlan_hdd_inited = ret_status ? 0 : 1;
7748 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007749 }
7750
7751 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07007752
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007753 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07007754
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007755 ret_status = hdd_driver_init();
7756 wlan_hdd_inited = ret_status ? 0 : 1;
7757 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007758}
7759
Jeff Johnson295189b2012-06-20 16:38:30 -07007760/**---------------------------------------------------------------------------
7761
Jeff Johnson76052702013-04-16 13:55:05 -07007762 \brief fwpath_changed_handler() - Handler Function
7763
7764 Handle changes to the fwpath parameter
7765
7766 \return - 0 for success, non zero for failure
7767
7768 --------------------------------------------------------------------------*/
7769static int fwpath_changed_handler(const char *kmessage,
7770 struct kernel_param *kp)
7771{
7772 int ret;
7773
7774 ret = param_set_copystring(kmessage, kp);
7775 if (0 == ret)
7776 ret = kickstart_driver();
7777 return ret;
7778}
7779
7780/**---------------------------------------------------------------------------
7781
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007782 \brief con_mode_handler() -
7783
7784 Handler function for module param con_mode when it is changed by userspace
7785 Dynamically linked - do nothing
7786 Statically linked - exit and init driver, as in rmmod and insmod
7787
Jeff Johnson76052702013-04-16 13:55:05 -07007788 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007789
Jeff Johnson76052702013-04-16 13:55:05 -07007790 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007791
7792 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07007793static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007794{
Jeff Johnson76052702013-04-16 13:55:05 -07007795 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007796
Jeff Johnson76052702013-04-16 13:55:05 -07007797 ret = param_set_int(kmessage, kp);
7798 if (0 == ret)
7799 ret = kickstart_driver();
7800 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007801}
7802#endif /* #ifdef MODULE */
7803
7804/**---------------------------------------------------------------------------
7805
Jeff Johnson295189b2012-06-20 16:38:30 -07007806 \brief hdd_get_conparam() -
7807
7808 This is the driver exit point (invoked when module is unloaded using rmmod)
7809
7810 \param - None
7811
7812 \return - tVOS_CON_MODE
7813
7814 --------------------------------------------------------------------------*/
7815tVOS_CON_MODE hdd_get_conparam ( void )
7816{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007817#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07007818 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007819#else
7820 return (tVOS_CON_MODE)curr_con_mode;
7821#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007822}
7823void hdd_set_conparam ( v_UINT_t newParam )
7824{
7825 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007826#ifndef MODULE
7827 curr_con_mode = con_mode;
7828#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007829}
7830/**---------------------------------------------------------------------------
7831
7832 \brief hdd_softap_sta_deauth() - function
7833
7834 This to take counter measure to handle deauth req from HDD
7835
7836 \param - pAdapter - Pointer to the HDD
7837
7838 \param - enable - boolean value
7839
7840 \return - None
7841
7842 --------------------------------------------------------------------------*/
7843
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007844VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07007845{
Jeff Johnson295189b2012-06-20 16:38:30 -07007846 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007847 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07007848
7849 ENTER();
7850
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007851 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
7852 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007853
7854 //Ignore request to deauth bcmc station
7855 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007856 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07007857
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007858 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07007859
7860 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007861 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07007862}
7863
7864/**---------------------------------------------------------------------------
7865
7866 \brief hdd_softap_sta_disassoc() - function
7867
7868 This to take counter measure to handle deauth req from HDD
7869
7870 \param - pAdapter - Pointer to the HDD
7871
7872 \param - enable - boolean value
7873
7874 \return - None
7875
7876 --------------------------------------------------------------------------*/
7877
7878void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
7879{
7880 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
7881
7882 ENTER();
7883
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307884 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007885
7886 //Ignore request to disassoc bcmc station
7887 if( pDestMacAddress[0] & 0x1 )
7888 return;
7889
7890 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
7891}
7892
7893void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
7894{
7895 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
7896
7897 ENTER();
7898
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307899 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007900
7901 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
7902}
7903
Jeff Johnson295189b2012-06-20 16:38:30 -07007904/**---------------------------------------------------------------------------
7905 *
7906 * \brief hdd_get__concurrency_mode() -
7907 *
7908 *
7909 * \param - None
7910 *
7911 * \return - CONCURRENCY MODE
7912 *
7913 * --------------------------------------------------------------------------*/
7914tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
7915{
7916 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
7917 hdd_context_t *pHddCtx;
7918
7919 if (NULL != pVosContext)
7920 {
7921 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
7922 if (NULL != pHddCtx)
7923 {
7924 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
7925 }
7926 }
7927
7928 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007929 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007930 return VOS_STA;
7931}
7932
7933/* Decide whether to allow/not the apps power collapse.
7934 * Allow apps power collapse if we are in connected state.
7935 * if not, allow only if we are in IMPS */
7936v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
7937{
7938 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08007939 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08007940 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07007941 hdd_config_t *pConfig = pHddCtx->cfg_ini;
7942 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7943 hdd_adapter_t *pAdapter = NULL;
7944 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08007945 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007946
Jeff Johnson295189b2012-06-20 16:38:30 -07007947 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7948 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007949
Yathish9f22e662012-12-10 14:21:35 -08007950 concurrent_state = hdd_get_concurrency_mode();
7951
7952#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7953 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
7954 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
7955 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
7956 return TRUE;
7957#endif
7958
Jeff Johnson295189b2012-06-20 16:38:30 -07007959 /*loop through all adapters. TBD fix for Concurrency */
7960 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7961 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7962 {
7963 pAdapter = pAdapterNode->pAdapter;
7964 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
7965 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7966 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08007967 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07007968 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08007969 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08007970 (eANI_BOOLEAN_TRUE == scanRspPending) ||
7971 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07007972 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08007973 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08007974 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
7975 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07007976 return FALSE;
7977 }
7978 }
7979 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
7980 pAdapterNode = pNext;
7981 }
7982 return TRUE;
7983}
7984
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08007985/* Decides whether to send suspend notification to Riva
7986 * if any adapter is in BMPS; then it is required */
7987v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
7988{
7989 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
7990 hdd_config_t *pConfig = pHddCtx->cfg_ini;
7991
7992 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
7993 {
7994 return TRUE;
7995 }
7996 return FALSE;
7997}
7998
Jeff Johnson295189b2012-06-20 16:38:30 -07007999void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8000{
8001 switch(mode)
8002 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008003 case VOS_STA_MODE:
8004 case VOS_P2P_CLIENT_MODE:
8005 case VOS_P2P_GO_MODE:
8006 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008007 pHddCtx->concurrency_mode |= (1 << mode);
8008 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008009 break;
8010 default:
8011 break;
8012
8013 }
8014 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8015 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8016}
8017
8018
8019void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8020{
8021 switch(mode)
8022 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008023 case VOS_STA_MODE:
8024 case VOS_P2P_CLIENT_MODE:
8025 case VOS_P2P_GO_MODE:
8026 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008027 pHddCtx->no_of_sessions[mode]--;
8028 if (!(pHddCtx->no_of_sessions[mode]))
8029 pHddCtx->concurrency_mode &= (~(1 << mode));
8030 break;
8031 default:
8032 break;
8033 }
8034 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8035 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8036}
8037
Jeff Johnsone7245742012-09-05 17:12:55 -07008038/**---------------------------------------------------------------------------
8039 *
8040 * \brief wlan_hdd_restart_init
8041 *
8042 * This function initalizes restart timer/flag. An internal function.
8043 *
8044 * \param - pHddCtx
8045 *
8046 * \return - None
8047 *
8048 * --------------------------------------------------------------------------*/
8049
8050static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8051{
8052 /* Initialize */
8053 pHddCtx->hdd_restart_retries = 0;
8054 atomic_set(&pHddCtx->isRestartInProgress, 0);
8055 vos_timer_init(&pHddCtx->hdd_restart_timer,
8056 VOS_TIMER_TYPE_SW,
8057 wlan_hdd_restart_timer_cb,
8058 pHddCtx);
8059}
8060/**---------------------------------------------------------------------------
8061 *
8062 * \brief wlan_hdd_restart_deinit
8063 *
8064 * This function cleans up the resources used. An internal function.
8065 *
8066 * \param - pHddCtx
8067 *
8068 * \return - None
8069 *
8070 * --------------------------------------------------------------------------*/
8071
8072static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8073{
8074
8075 VOS_STATUS vos_status;
8076 /* Block any further calls */
8077 atomic_set(&pHddCtx->isRestartInProgress, 1);
8078 /* Cleanup */
8079 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8080 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008081 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008082 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8083 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008084 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008085
8086}
8087
8088/**---------------------------------------------------------------------------
8089 *
8090 * \brief wlan_hdd_framework_restart
8091 *
8092 * This function uses a cfg80211 API to start a framework initiated WLAN
8093 * driver module unload/load.
8094 *
8095 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8096 *
8097 *
8098 * \param - pHddCtx
8099 *
8100 * \return - VOS_STATUS_SUCCESS: Success
8101 * VOS_STATUS_E_EMPTY: Adapter is Empty
8102 * VOS_STATUS_E_NOMEM: No memory
8103
8104 * --------------------------------------------------------------------------*/
8105
8106static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8107{
8108 VOS_STATUS status = VOS_STATUS_SUCCESS;
8109 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008110 int len = (sizeof (struct ieee80211_mgmt));
8111 struct ieee80211_mgmt *mgmt = NULL;
8112
8113 /* Prepare the DEAUTH managment frame with reason code */
8114 mgmt = kzalloc(len, GFP_KERNEL);
8115 if(mgmt == NULL)
8116 {
8117 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8118 "%s: memory allocation failed (%d bytes)", __func__, len);
8119 return VOS_STATUS_E_NOMEM;
8120 }
8121 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008122
8123 /* Iterate over all adapters/devices */
8124 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8125 do
8126 {
8127 if( (status == VOS_STATUS_SUCCESS) &&
8128 pAdapterNode &&
8129 pAdapterNode->pAdapter)
8130 {
8131 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8132 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8133 pAdapterNode->pAdapter->dev->name,
8134 pAdapterNode->pAdapter->device_mode,
8135 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008136 /*
8137 * CFG80211 event to restart the driver
8138 *
8139 * 'cfg80211_send_unprot_deauth' sends a
8140 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8141 * of SME(Linux Kernel) state machine.
8142 *
8143 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8144 * the driver.
8145 *
8146 */
8147
8148 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008149 }
8150 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8151 pAdapterNode = pNext;
8152 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8153
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008154
8155 /* Free the allocated management frame */
8156 kfree(mgmt);
8157
Jeff Johnsone7245742012-09-05 17:12:55 -07008158 /* Retry until we unload or reach max count */
8159 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8160 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8161
8162 return status;
8163
8164}
8165/**---------------------------------------------------------------------------
8166 *
8167 * \brief wlan_hdd_restart_timer_cb
8168 *
8169 * Restart timer callback. An internal function.
8170 *
8171 * \param - User data:
8172 *
8173 * \return - None
8174 *
8175 * --------------------------------------------------------------------------*/
8176
8177void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8178{
8179 hdd_context_t *pHddCtx = usrDataForCallback;
8180 wlan_hdd_framework_restart(pHddCtx);
8181 return;
8182
8183}
8184
8185
8186/**---------------------------------------------------------------------------
8187 *
8188 * \brief wlan_hdd_restart_driver
8189 *
8190 * This function sends an event to supplicant to restart the WLAN driver.
8191 *
8192 * This function is called from vos_wlanRestart.
8193 *
8194 * \param - pHddCtx
8195 *
8196 * \return - VOS_STATUS_SUCCESS: Success
8197 * VOS_STATUS_E_EMPTY: Adapter is Empty
8198 * VOS_STATUS_E_ALREADY: Request already in progress
8199
8200 * --------------------------------------------------------------------------*/
8201VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8202{
8203 VOS_STATUS status = VOS_STATUS_SUCCESS;
8204
8205 /* A tight check to make sure reentrancy */
8206 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8207 {
8208 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8209 "%s: WLAN restart is already in progress", __func__);
8210
8211 return VOS_STATUS_E_ALREADY;
8212 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008213 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008214#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008215 wcnss_reset_intr();
8216#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008217
Jeff Johnsone7245742012-09-05 17:12:55 -07008218 return status;
8219}
8220
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008221/*
8222 * API to find if there is any STA or P2P-Client is connected
8223 */
8224VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8225{
8226 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8227}
Jeff Johnsone7245742012-09-05 17:12:55 -07008228
Jeff Johnson295189b2012-06-20 16:38:30 -07008229//Register the module init/exit functions
8230module_init(hdd_module_init);
8231module_exit(hdd_module_exit);
8232
8233MODULE_LICENSE("Dual BSD/GPL");
8234MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8235MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8236
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008237module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8238 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008239
Jeff Johnson76052702013-04-16 13:55:05 -07008240module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07008241 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);