blob: 0068dc585188fa0cd5b914a77dec87b1a0031398 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700112#include <linux/ctype.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#include <mach/subsystem_restart.h>
114#include <wlan_hdd_hostapd.h>
115#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700117#include "wlan_hdd_dev_pwr.h"
118#ifdef WLAN_BTAMP_FEATURE
119#include "bap_hdd_misc.h"
120#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700122#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800123#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530124#ifdef FEATURE_WLAN_TDLS
125#include "wlan_hdd_tdls.h"
126#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700127#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700128
129#ifdef MODULE
130#define WLAN_MODULE_NAME module_name(THIS_MODULE)
131#else
132#define WLAN_MODULE_NAME "wlan"
133#endif
134
135#ifdef TIMER_MANAGER
136#define TIMER_MANAGER_STR " +TIMER_MANAGER"
137#else
138#define TIMER_MANAGER_STR ""
139#endif
140
141#ifdef MEMORY_DEBUG
142#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
143#else
144#define MEMORY_DEBUG_STR ""
145#endif
146
147/* the Android framework expects this param even though we don't use it */
148#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700149static char fwpath_buffer[BUF_LEN];
150static struct kparam_string fwpath = {
151 .string = fwpath_buffer,
152 .maxlen = BUF_LEN,
153};
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700154#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700155static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700156#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700157
Jeff Johnsone7245742012-09-05 17:12:55 -0700158/*
159 * The rate at which the driver sends RESTART event to supplicant
160 * once the function 'vos_wlanRestart()' is called
161 *
162 */
163#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
164#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700165
166/*
167 * Size of Driver command strings from upper layer
168 */
169#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
170#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
171
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700172/*
173 * Driver miracast parameters 0-Disabled
174 * 1-Source, 2-Sink
175 */
176#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
177#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
178
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800179#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700180static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700181#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700182/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700183static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700184
185//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700186static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
187static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
188static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
189void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800190void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700191
Jeff Johnson295189b2012-06-20 16:38:30 -0700192v_U16_t hdd_select_queue(struct net_device *dev,
193 struct sk_buff *skb);
194
195#ifdef WLAN_FEATURE_PACKET_FILTERING
196static void hdd_set_multicast_list(struct net_device *dev);
197#endif
198
199void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700200int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700201
202extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800203#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
204void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
205static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700206static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
207 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
208 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700209static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
210 tANI_U8 *pTargetApBssid,
211 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800212#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700213static int hdd_netdev_notifier_call(struct notifier_block * nb,
214 unsigned long state,
215 void *ndev)
216{
217 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700218 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700219 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700220#ifdef WLAN_BTAMP_FEATURE
221 VOS_STATUS status;
222 hdd_context_t *pHddCtx;
223#endif
224
225 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700226 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700227 (strncmp(dev->name, "p2p", 3)))
228 return NOTIFY_DONE;
229
230 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700231 return NOTIFY_DONE;
232
Jeff Johnson295189b2012-06-20 16:38:30 -0700233 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700234 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700235
Jeff Johnson27cee452013-03-27 11:10:24 -0700236 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700237 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800238 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700239 VOS_ASSERT(0);
240 return NOTIFY_DONE;
241 }
242
Jeff Johnson27cee452013-03-27 11:10:24 -0700243 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
244 if (NULL == pHddCtx)
245 {
246 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
247 VOS_ASSERT(0);
248 return NOTIFY_DONE;
249 }
250
251 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
252 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700253
254 switch (state) {
255 case NETDEV_REGISTER:
256 break;
257
258 case NETDEV_UNREGISTER:
259 break;
260
261 case NETDEV_UP:
262 break;
263
264 case NETDEV_DOWN:
265 break;
266
267 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700268 if(TRUE == pAdapter->isLinkUpSvcNeeded)
269 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270 break;
271
272 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700273 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700274 {
275 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800276 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530277 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700278 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800279 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700280 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
281 if(!result)
282 {
283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800284 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700285 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700286 }
287 }
288 else
289 {
290 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700291 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700292 }
293#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700294 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700295 status = WLANBAP_StopAmp();
296 if(VOS_STATUS_SUCCESS != status )
297 {
298 pHddCtx->isAmpAllowed = VOS_TRUE;
299 hddLog(VOS_TRACE_LEVEL_FATAL,
300 "%s: Failed to stop AMP", __func__);
301 }
302 else
303 {
304 //a state m/c implementation in PAL is TBD to avoid this delay
305 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700306 if ( pHddCtx->isAmpAllowed )
307 {
308 WLANBAP_DeregisterFromHCI();
309 pHddCtx->isAmpAllowed = VOS_FALSE;
310 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700311 }
312#endif //WLAN_BTAMP_FEATURE
313 break;
314
315 default:
316 break;
317 }
318
319 return NOTIFY_DONE;
320}
321
322struct notifier_block hdd_netdev_notifier = {
323 .notifier_call = hdd_netdev_notifier_call,
324};
325
326/*---------------------------------------------------------------------------
327 * Function definitions
328 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700329void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
330void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700331//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700332static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700333#ifndef MODULE
334/* current con_mode - used only for statically linked driver
335 * con_mode is changed by userspace to indicate a mode change which will
336 * result in calling the module exit and init functions. The module
337 * exit function will clean up based on the value of con_mode prior to it
338 * being changed by userspace. So curr_con_mode records the current con_mode
339 * for exit when con_mode becomes the next mode for init
340 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700341static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700342#endif
343
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800344/**---------------------------------------------------------------------------
345
346 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
347
348 Called immediately after the cfg.ini is read in order to configure
349 the desired trace levels.
350
351 \param - moduleId - module whose trace level is being configured
352 \param - bitmask - bitmask of log levels to be enabled
353
354 \return - void
355
356 --------------------------------------------------------------------------*/
357static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
358{
359 wpt_tracelevel level;
360
361 /* if the bitmask is the default value, then a bitmask was not
362 specified in cfg.ini, so leave the logging level alone (it
363 will remain at the "compiled in" default value) */
364 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
365 {
366 return;
367 }
368
369 /* a mask was specified. start by disabling all logging */
370 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
371
372 /* now cycle through the bitmask until all "set" bits are serviced */
373 level = VOS_TRACE_LEVEL_FATAL;
374 while (0 != bitmask)
375 {
376 if (bitmask & 1)
377 {
378 vos_trace_setValue(moduleId, level, 1);
379 }
380 level++;
381 bitmask >>= 1;
382 }
383}
384
385
Jeff Johnson295189b2012-06-20 16:38:30 -0700386/**---------------------------------------------------------------------------
387
388 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
389
390 Called immediately after the cfg.ini is read in order to configure
391 the desired trace levels in the WDI.
392
393 \param - moduleId - module whose trace level is being configured
394 \param - bitmask - bitmask of log levels to be enabled
395
396 \return - void
397
398 --------------------------------------------------------------------------*/
399static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
400{
401 wpt_tracelevel level;
402
403 /* if the bitmask is the default value, then a bitmask was not
404 specified in cfg.ini, so leave the logging level alone (it
405 will remain at the "compiled in" default value) */
406 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
407 {
408 return;
409 }
410
411 /* a mask was specified. start by disabling all logging */
412 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
413
414 /* now cycle through the bitmask until all "set" bits are serviced */
415 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
416 while (0 != bitmask)
417 {
418 if (bitmask & 1)
419 {
420 wpalTraceSetLevel(moduleId, level, 1);
421 }
422 level++;
423 bitmask >>= 1;
424 }
425}
Jeff Johnson295189b2012-06-20 16:38:30 -0700426
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530427/*
428 * FUNCTION: wlan_hdd_validate_context
429 * This function is used to check the HDD context
430 */
431int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
432{
433 ENTER();
434
435 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
436 {
437 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
438 "%s: HDD context is Null", __func__);
439 return -ENODEV;
440 }
441
442 if (pHddCtx->isLogpInProgress)
443 {
444 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
445 "%s: LOGP in Progress. Ignore!!!", __func__);
446 return -EAGAIN;
447 }
448
449 if (pHddCtx->isLoadUnloadInProgress)
450 {
451 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
452 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
453 return -EAGAIN;
454 }
455 return 0;
456}
457
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530458void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
459{
460 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
461 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
462 hdd_config_t *cfg_param;
463 eCsrPhyMode phyMode;
464
465 if (NULL == pHddCtx)
466 {
467 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
468 "HDD Context is null !!");
469 return ;
470 }
471
472 cfg_param = pHddCtx->cfg_ini;
473
474 if (NULL == cfg_param)
475 {
476 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
477 "cfg_params not available !!");
478 return ;
479 }
480
481 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
482
483 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
484 {
485 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
486 (eCSR_DOT11_MODE_11ac == phyMode) ||
487 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
488 {
489 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
490 "Setting phymode to 11n!!");
491 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
492 }
493 }
494 else
495 {
496 /*New country Supports 11ac as well resetting value back from .ini*/
497 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
498 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
499 return ;
500 }
501
502 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
503 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
504 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
505 {
506 VOS_STATUS vosStatus;
507
508 // need to issue a disconnect to CSR.
509 INIT_COMPLETION(pAdapter->disconnect_comp_var);
510 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
511 pAdapter->sessionId,
512 eCSR_DISCONNECT_REASON_UNSPECIFIED );
513
514 if (VOS_STATUS_SUCCESS == vosStatus)
515 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
516 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
517
518 }
519}
520
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700521void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
522{
523 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
524 hdd_config_t *cfg_param;
525
526 if (NULL == pHddCtx)
527 {
528 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
529 "HDD Context is null !!");
530 return ;
531 }
532
533 cfg_param = pHddCtx->cfg_ini;
534
535 if (NULL == cfg_param)
536 {
537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
538 "cfg_params not available !!");
539 return ;
540 }
541
542 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
543 {
544 /*New country doesn't support DFS */
545 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
546 }
547 else
548 {
549 /*New country Supports DFS as well resetting value back from .ini*/
550 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
551 }
552
553}
554
Rajeev79dbe4c2013-10-05 11:03:42 +0530555#ifdef FEATURE_WLAN_BATCH_SCAN
556
557/**---------------------------------------------------------------------------
558
559 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
560 input string
561
562 This function extracts assigned integer from string in below format:
563 "STRING=10" : extracts integer 10 from this string
564
565 \param - pInPtr Pointer to input string
566 \param - base Base for string to int conversion(10 for decimal 16 for hex)
567 \param - pOutPtr Pointer to variable in which extracted integer needs to be
568 assigned
569 \param - pLastArg to tell whether it is last arguement in input string or
570 not
571
572 \return - NULL for failure cases
573 pointer to next arguement in input string for success cases
574 --------------------------------------------------------------------------*/
575static tANI_U8 *
576hdd_extract_assigned_int_from_str
577(
578 tANI_U8 *pInPtr,
579 tANI_U8 base,
580 tANI_U32 *pOutPtr,
581 tANI_U8 *pLastArg
582)
583{
584 int tempInt;
585 int v = 0;
586 char buf[32];
587 int val = 0;
588 *pLastArg = FALSE;
589
590 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
591 if (NULL == pInPtr)
592 {
593 return NULL;
594 }
595
596 pInPtr++;
597
598 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
599
600 val = sscanf(pInPtr, "%32s ", buf);
601 if (val < 0 && val > strlen(pInPtr))
602 {
603 return NULL;
604 }
605 pInPtr += val;
606 v = kstrtos32(buf, base, &tempInt);
607 if (v < 0)
608 {
609 return NULL;
610 }
611 *pOutPtr = tempInt;
612
613 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
614 if (NULL == pInPtr)
615 {
616 *pLastArg = TRUE;
617 return NULL;
618 }
619 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
620
621 return pInPtr;
622}
623
624/**---------------------------------------------------------------------------
625
626 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
627 input string
628
629 This function extracts assigned character from string in below format:
630 "STRING=A" : extracts char 'A' from this string
631
632 \param - pInPtr Pointer to input string
633 \param - pOutPtr Pointer to variable in which extracted char needs to be
634 assigned
635 \param - pLastArg to tell whether it is last arguement in input string or
636 not
637
638 \return - NULL for failure cases
639 pointer to next arguement in input string for success cases
640 --------------------------------------------------------------------------*/
641static tANI_U8 *
642hdd_extract_assigned_char_from_str
643(
644 tANI_U8 *pInPtr,
645 tANI_U8 *pOutPtr,
646 tANI_U8 *pLastArg
647)
648{
649 *pLastArg = FALSE;
650
651 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
652 if (NULL == pInPtr)
653 {
654 return NULL;
655 }
656
657 pInPtr++;
658
659 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
660
661 *pOutPtr = *pInPtr;
662
663 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
664 if (NULL == pInPtr)
665 {
666 *pLastArg = TRUE;
667 return NULL;
668 }
669 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
670
671 return pInPtr;
672}
673
674
675/**---------------------------------------------------------------------------
676
677 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
678
679 This function parses set batch scan command in below format:
680 WLS_BATCHING_SET <space> followed by below arguements
681 "SCANFREQ=XX" : Optional defaults to 30 sec
682 "MSCAN=XX" : Required number of scans to attempt to batch
683 "BESTN=XX" : Best Network (RSSI) defaults to 16
684 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
685 A. implies only 5 GHz , B. implies only 2.4GHz
686 "RTT=X" : optional defaults to 0
687 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
688 error
689
690 For example input commands:
691 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
692 translated into set batch scan with following parameters:
693 a) Frequence 60 seconds
694 b) Batch 10 scans together
695 c) Best RSSI to be 20
696 d) 5GHz band only
697 e) RTT is equal to 0
698
699 \param - pValue Pointer to input channel list
700 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
701
702 \return - 0 for success non-zero for failure
703
704 --------------------------------------------------------------------------*/
705static int
706hdd_parse_set_batchscan_command
707(
708 tANI_U8 *pValue,
709 tSirSetBatchScanReq *pHddSetBatchScanReq
710)
711{
712 tANI_U8 *inPtr = pValue;
713 tANI_U8 val = 0;
714 tANI_U8 lastArg = 0;
715
716 /*initialize default values*/
717 pHddSetBatchScanReq->scanFrequency = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
718 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
719 pHddSetBatchScanReq->rtt = 0;
720 pHddSetBatchScanReq->bestNetwork = HDD_SET_BATCH_SCAN_BEST_NETWORK;
721
722 /*go to space after WLS_BATCHING_SET command*/
723 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
724 /*no argument after the command*/
725 if (NULL == inPtr)
726 {
727 return -EINVAL;
728 }
729
730 /*no space after the command*/
731 else if (SPACE_ASCII_VALUE != *inPtr)
732 {
733 return -EINVAL;
734 }
735
736 /*removing empty spaces*/
737 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
738
739 /*no argument followed by spaces*/
740 if ('\0' == *inPtr)
741 {
742 return -EINVAL;
743 }
744
745 /*check and parse SCANFREQ*/
746 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
747 {
748 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
749 &pHddSetBatchScanReq->scanFrequency, &lastArg);
750 if ( (NULL == inPtr) || (TRUE == lastArg))
751 {
752 return -EINVAL;
753 }
754 }
755
756 /*check and parse MSCAN*/
757 if ((strncmp(inPtr, "MSCAN", 5) == 0))
758 {
759 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
760 &pHddSetBatchScanReq->numberOfScansToBatch, &lastArg);
761 if (TRUE == lastArg)
762 {
763 goto done;
764 }
765 else if (NULL == inPtr)
766 {
767 return -EINVAL;
768 }
769 }
770 else
771 {
772 return -EINVAL;
773 }
774
775 /*check and parse BESTN*/
776 if ((strncmp(inPtr, "BESTN", 5) == 0))
777 {
778 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
779 &pHddSetBatchScanReq->bestNetwork, &lastArg);
780 if (TRUE == lastArg)
781 {
782 goto done;
783 }
784 else if (NULL == inPtr)
785 {
786 return -EINVAL;
787 }
788 }
789
790 /*check and parse CHANNEL*/
791 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
792 {
793 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
794 if (TRUE == lastArg)
795 {
796 goto done;
797 }
798 else if (NULL == inPtr)
799 {
800 return -EINVAL;
801 }
802 if (('A' == val) || ('a' == val))
803 {
804 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
805 }
806 else if (('B' == val) || ('b' == val))
807 {
808 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
809 }
810 else
811 {
812 return -EINVAL;
813 }
814 }
815
816 /*check and parse RTT*/
817 if ((strncmp(inPtr, "RTT", 3) == 0))
818 {
819 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
820 &pHddSetBatchScanReq->rtt, &lastArg);
821 if (TRUE == lastArg)
822 {
823 goto done;
824 }
825 if (NULL == inPtr)
826 {
827 return -EINVAL;
828 }
829 }
830
831
832done:
833
834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
835 "Received WLS_BATCHING_SET with SCANFREQ=%d "
836 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
837 pHddSetBatchScanReq->scanFrequency,
838 pHddSetBatchScanReq->numberOfScansToBatch,
839 pHddSetBatchScanReq->bestNetwork,
840 pHddSetBatchScanReq->rfBand,
841 pHddSetBatchScanReq->rtt);
842
843 return 0;
844}/*End of hdd_parse_set_batchscan_command*/
845
846/**---------------------------------------------------------------------------
847
848 \brief hdd_set_batch_scan_req_callback () - This function is called after
849 receiving set batch scan response from FW and it saves set batch scan
850 response data FW to HDD context and sets the completion event on
851 which hdd_ioctl is waiting
852
853 \param - callbackContext Pointer to HDD adapter
854 \param - pRsp Pointer to set batch scan response data received from FW
855
856 \return - nothing
857
858 --------------------------------------------------------------------------*/
859static void hdd_set_batch_scan_req_callback
860(
861 void *callbackContext,
862 tSirSetBatchScanRsp *pRsp
863)
864{
865 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
866 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
867
868 /*sanity check*/
869 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
870 {
871 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
872 "%s: Invalid pAdapter magic", __func__);
873 VOS_ASSERT(0);
874 return;
875 }
876 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
877
878 /*save set batch scan response*/
879 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
880
881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
882 "Received set batch scan rsp from FW with nScansToBatch=%d",
883 pHddSetBatchScanRsp->nScansToBatch);
884
885 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
886 complete(&pAdapter->hdd_set_batch_scan_req_var);
887
888 return;
889}/*End of hdd_set_batch_scan_req_callback*/
890
891
892/**---------------------------------------------------------------------------
893
894 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
895 info in hdd batch scan response queue
896
897 \param - pAdapter Pointer to hdd adapter
898 \param - pAPMetaInfo Pointer to access point meta info
899 \param - scanId scan ID of batch scan response
900 \param - isLastAp tells whether AP is last AP in batch scan response or not
901
902 \return - nothing
903
904 --------------------------------------------------------------------------*/
905static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
906 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
907{
908 tHddBatchScanRsp *pHead;
909 tHddBatchScanRsp *pNode;
910 tHddBatchScanRsp *pPrev;
911 tHddBatchScanRsp *pTemp;
912 tANI_U8 ssidLen;
913
914 /*head of hdd batch scan response queue*/
915 pHead = pAdapter->pBatchScanRsp;
916
917 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
918 if (NULL == pNode)
919 {
920 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
921 "%s: Could not allocate memory", __func__);
922 VOS_ASSERT(0);
923 return;
924 }
925
926 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
927 sizeof(pNode->ApInfo.bssid));
928 ssidLen = strlen(pApMetaInfo->ssid);
929 if (SIR_MAX_SSID_SIZE < ssidLen)
930 {
931 /*invalid scan result*/
932 vos_mem_free(pNode);
933 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
934 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
935 return;
936 }
937 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
938 /*null terminate ssid*/
939 pNode->ApInfo.ssid[ssidLen] = '\0';
940 pNode->ApInfo.ch = pApMetaInfo->ch;
941 pNode->ApInfo.rssi = pApMetaInfo->rssi;
942 pNode->ApInfo.age = pApMetaInfo->timestamp;
943 pNode->ApInfo.batchId = scanId;
944 pNode->ApInfo.isLastAp = isLastAp;
945
946 pNode->pNext = NULL;
947 if (NULL == pHead)
948 {
949 pAdapter->pBatchScanRsp = pNode;
950 }
951 else
952 {
953 pTemp = pHead;
954 while (NULL != pTemp)
955 {
956 pPrev = pTemp;
957 pTemp = pTemp->pNext;
958 }
959 pPrev->pNext = pNode;
960 }
961
962 return;
963}/*End of hdd_populate_batch_scan_rsp_queue*/
964
965/**---------------------------------------------------------------------------
966
967 \brief hdd_batch_scan_result_ind_callback () - This function is called after
968 receiving batch scan response indication from FW. It saves get batch scan
969 response data in HDD batch scan response queue. This callback sets the
970 completion event on which hdd_ioctl is waiting only after getting complete
971 batch scan response data from FW
972
973 \param - callbackContext Pointer to HDD adapter
974 \param - pRsp Pointer to get batch scan response data received from FW
975
976 \return - nothing
977
978 --------------------------------------------------------------------------*/
979static void hdd_batch_scan_result_ind_callback
980(
981 void *callbackContext,
982 void *pRsp
983)
984{
985 v_BOOL_t isLastAp;
986 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -0700987 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +0530988 tANI_U32 numberScanList;
989 tANI_U32 nextScanListOffset;
990 tANI_U32 nextApMetaInfoOffset;
991 hdd_adapter_t* pAdapter;
992 tpSirBatchScanList pScanList;
993 tpSirBatchScanNetworkInfo pApMetaInfo;
994 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
995 tSirSetBatchScanReq *pReq;
996
997 pAdapter = (hdd_adapter_t *)callbackContext;
998 /*sanity check*/
999 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1000 {
1001 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1002 "%s: Invalid pAdapter magic", __func__);
1003 VOS_ASSERT(0);
1004 return;
1005 }
1006
1007 /*initialize locals*/
1008 pReq = &pAdapter->hddSetBatchScanReq;
1009 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1010 isLastAp = FALSE;
1011 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001012 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301013 numberScanList = 0;
1014 nextScanListOffset = 0;
1015 nextApMetaInfoOffset = 0;
1016 pScanList = NULL;
1017 pApMetaInfo = NULL;
1018
1019 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1020 {
1021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1022 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1023 isLastAp = TRUE;
1024 goto done;
1025 }
1026
1027 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1028 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1029 "Batch scan rsp: numberScalList %d", numberScanList);
1030
1031 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1032 {
1033 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1034 "%s: numberScanList %d", __func__, numberScanList);
1035 isLastAp = TRUE;
1036 goto done;
1037 }
1038
1039 while (numberScanList)
1040 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001041 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301042 nextScanListOffset);
1043 if (NULL == pScanList)
1044 {
1045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1046 "%s: pScanList is %p", __func__, pScanList);
1047 isLastAp = TRUE;
1048 goto done;
1049 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001050 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301051 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001052 "Batch scan rsp: numApMetaInfo %d scanId %d",
1053 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301054
1055 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1056 {
1057 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1058 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1059 isLastAp = TRUE;
1060 goto done;
1061 }
1062
Rajeev Kumarce651e42013-10-21 18:57:15 -07001063 /*Initialize next AP meta info offset for next scan list*/
1064 nextApMetaInfoOffset = 0;
1065
Rajeev79dbe4c2013-10-05 11:03:42 +05301066 while (numApMetaInfo)
1067 {
1068 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1069 nextApMetaInfoOffset);
1070 if (NULL == pApMetaInfo)
1071 {
1072 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1073 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1074 isLastAp = TRUE;
1075 goto done;
1076 }
1077 /*calculate AP age*/
1078 pApMetaInfo->timestamp =
1079 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1080
1081 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1082 "%s: bssId 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x "
1083 "ch %d rssi %d timestamp %d", __func__,
1084 pApMetaInfo->bssid[0],pApMetaInfo->bssid[1],
1085 pApMetaInfo->bssid[2],pApMetaInfo->bssid[3],
1086 pApMetaInfo->bssid[4],pApMetaInfo->bssid[5],
1087 pApMetaInfo->ch, pApMetaInfo->rssi,
1088 pApMetaInfo->timestamp);
1089
1090 /*mark last AP in batch scan response*/
1091 if ((TRUE == pBatchScanRsp->isLastResult) &&
1092 (1 == numberScanList) && (1 == numApMetaInfo))
1093 {
1094 isLastAp = TRUE;
1095 }
1096
1097 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1098 /*store batch scan repsonse in hdd queue*/
1099 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1100 pScanList->scanId, isLastAp);
1101 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1102
1103 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1104 numApMetaInfo--;
1105 }
1106
Rajeev Kumarce651e42013-10-21 18:57:15 -07001107 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1108 + (sizeof(tSirBatchScanNetworkInfo)
1109 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301110 numberScanList--;
1111 }
1112
1113done:
1114
1115 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1116 requested from hdd_ioctl*/
1117 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1118 (TRUE == isLastAp))
1119 {
1120 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1121 complete(&pAdapter->hdd_get_batch_scan_req_var);
1122 }
1123
1124 return;
1125}/*End of hdd_batch_scan_result_ind_callback*/
1126
1127/**---------------------------------------------------------------------------
1128
1129 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1130 response as per batch scan FR request format by putting proper markers
1131
1132 \param - pDest pointer to destination buffer
1133 \param - cur_len current length
1134 \param - tot_len total remaining size which can be written to user space
1135 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1136 \param - pAdapter Pointer to HDD adapter
1137
1138 \return - ret no of characters written
1139
1140 --------------------------------------------------------------------------*/
1141static tANI_U32
1142hdd_format_batch_scan_rsp
1143(
1144 tANI_U8 *pDest,
1145 tANI_U32 cur_len,
1146 tANI_U32 tot_len,
1147 tHddBatchScanRsp *pApMetaInfo,
1148 hdd_adapter_t* pAdapter
1149)
1150{
1151 tANI_U32 ret = 0;
1152 tANI_U32 rem_len = 0;
1153 tANI_U8 temp_len = 0;
1154 tANI_U8 temp_total_len = 0;
1155 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1156 tANI_U8 *pTemp = temp;
1157
1158 /*Batch scan reponse needs to be returned to user space in
1159 following format:
1160 "scancount=X\n" where X is the number of scans in current batch
1161 batch
1162 "trunc\n" optional present if current scan truncated
1163 "bssid=XX:XX:XX:XX:XX:XX\n"
1164 "ssid=XXXX\n"
1165 "freq=X\n" frequency in Mhz
1166 "level=XX\n"
1167 "age=X\n" ms
1168 "dist=X\n" cm (-1 if not available)
1169 "errror=X\n" (-1if not available)
1170 "====\n" (end of ap marker)
1171 "####\n" (end of scan marker)
1172 "----\n" (end of results)*/
1173 /*send scan result in above format to user space based on
1174 available length*/
1175 /*The GET response may have more data than the driver can return in its
1176 buffer. In that case the buffer should be filled to the nearest complete
1177 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1178 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1179 The final buffer should end with "----\n"*/
1180
1181 /*sanity*/
1182 if (cur_len > tot_len)
1183 {
1184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1185 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1186 return 0;
1187 }
1188 else
1189 {
1190 rem_len = (tot_len - cur_len);
1191 }
1192
1193 /*end scan marker*/
1194 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1195 {
1196 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1197 pTemp += temp_len;
1198 temp_total_len += temp_len;
1199 }
1200
1201 /*bssid*/
1202 temp_len = snprintf(pTemp, sizeof(temp),
1203 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1204 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1205 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1206 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1207 pTemp += temp_len;
1208 temp_total_len += temp_len;
1209
1210 /*ssid*/
1211 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1212 pApMetaInfo->ApInfo.ssid);
1213 pTemp += temp_len;
1214 temp_total_len += temp_len;
1215
1216 /*freq*/
1217 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
1218 pApMetaInfo->ApInfo.ch);
1219 pTemp += temp_len;
1220 temp_total_len += temp_len;
1221
1222 /*level*/
1223 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1224 pApMetaInfo->ApInfo.rssi);
1225 pTemp += temp_len;
1226 temp_total_len += temp_len;
1227
1228 /*age*/
1229 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%ld\n",
1230 pApMetaInfo->ApInfo.age);
1231 pTemp += temp_len;
1232 temp_total_len += temp_len;
1233
1234 /*dist*/
1235 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1236 pTemp += temp_len;
1237 temp_total_len += temp_len;
1238
1239 /*error*/
1240 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1241 pTemp += temp_len;
1242 temp_total_len += temp_len;
1243
1244 /*end AP marker*/
1245 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1246 pTemp += temp_len;
1247 temp_total_len += temp_len;
1248
1249 /*last AP in batch scan response*/
1250 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1251 {
1252 /*end scan marker*/
1253 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1254 pTemp += temp_len;
1255 temp_total_len += temp_len;
1256
1257 /*end batch scan result marker*/
1258 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1259 pTemp += temp_len;
1260 temp_total_len += temp_len;
1261 }
1262
1263 if (temp_total_len < rem_len)
1264 {
1265 ret = temp_total_len + 1;
1266 strlcpy(pDest, temp, ret);
1267 pAdapter->isTruncated = FALSE;
1268 }
1269 else
1270 {
1271 pAdapter->isTruncated = TRUE;
1272 if (rem_len >= strlen("%%%%"))
1273 {
1274 ret = snprintf(pDest, strlen("%%%%"), "%%%%");
1275 }
1276 {
1277 ret = 0;
1278 }
1279 }
1280
1281 return ret;
1282
1283}/*End of hdd_format_batch_scan_rsp*/
1284
1285/**---------------------------------------------------------------------------
1286
1287 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1288 buffer starting with head of hdd batch scan response queue
1289
1290 \param - pAdapter Pointer to HDD adapter
1291 \param - pDest Pointer to user data buffer
1292 \param - cur_len current offset in user buffer
1293 \param - rem_len remaining no of bytes in user buffer
1294
1295 \return - number of bytes written in user buffer
1296
1297 --------------------------------------------------------------------------*/
1298
1299tANI_U32 hdd_populate_user_batch_scan_rsp
1300(
1301 hdd_adapter_t* pAdapter,
1302 tANI_U8 *pDest,
1303 tANI_U32 cur_len,
1304 tANI_U32 rem_len
1305)
1306{
1307 tHddBatchScanRsp *pHead;
1308 tHddBatchScanRsp *pPrev;
1309 tANI_U32 len;
1310
1311 pAdapter->prev_batch_id = 0;
1312 pAdapter->isTruncated = FALSE;
1313
1314 /*head of hdd batch scan response queue*/
1315 pHead = pAdapter->pBatchScanRsp;
1316 while (pHead)
1317 {
1318 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1319 pAdapter);
1320 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001321 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301322 cur_len += len;
1323 if(TRUE == pAdapter->isTruncated)
1324 {
1325 /*result is truncated return rest of scan rsp in next req*/
1326 cur_len = rem_len;
1327 break;
1328 }
1329 pPrev = pHead;
1330 pHead = pHead->pNext;
1331 pAdapter->pBatchScanRsp = pHead;
1332 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1333 vos_mem_free(pPrev);
1334 }
1335
1336 return cur_len;
1337}/*End of hdd_populate_user_batch_scan_rsp*/
1338
1339/**---------------------------------------------------------------------------
1340
1341 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1342 scan response data from HDD queue to user space
1343 It does following in detail:
1344 a) if HDD has enough data in its queue then it 1st copies data to user
1345 space and then send get batch scan indication message to FW. In this
1346 case it does not wait on any event and batch scan response data will
1347 be populated in HDD response queue in MC thread context after receiving
1348 indication from FW
1349 b) else send get batch scan indication message to FW and wait on an event
1350 which will be set once HDD receives complete batch scan response from
1351 FW and then this function returns batch scan response to user space
1352
1353 \param - pAdapter Pointer to HDD adapter
1354 \param - pPrivData Pointer to priv_data
1355
1356 \return - 0 for success -EFAULT for failure
1357
1358 --------------------------------------------------------------------------*/
1359
1360int hdd_return_batch_scan_rsp_to_user
1361(
1362 hdd_adapter_t* pAdapter,
1363 hdd_priv_data_t *pPrivData,
1364 tANI_U8 *command
1365)
1366{
1367 tANI_U8 *pDest;
1368 tANI_U32 count = 0;
1369 tANI_U32 len = 0;
1370 tANI_U32 cur_len = 0;
1371 tANI_U32 rem_len = 0;
1372 eHalStatus halStatus;
1373 unsigned long rc;
1374 tSirTriggerBatchScanResultInd *pReq;
1375
1376 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1377 pReq->param = 0;/*batch scan client*/
1378 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1379 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1380
1381 cur_len = pPrivData->used_len;
1382 if (pPrivData->total_len > pPrivData->used_len)
1383 {
1384 rem_len = pPrivData->total_len - pPrivData->used_len;
1385 }
1386 else
1387 {
1388 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1389 "%s: Invalid user data buffer total_len %d used_len %d",
1390 __func__, pPrivData->total_len, pPrivData->used_len);
1391 return -EFAULT;
1392 }
1393
1394 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1395 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1396 cur_len, rem_len);
1397 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1398
1399 /*enough scan result available in cache to return to user space or
1400 scan result needs to be fetched 1st from fw and then return*/
1401 if (len < rem_len)
1402 {
1403 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1404 halStatus = sme_TriggerBatchScanResultInd(
1405 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1406 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1407 pAdapter);
1408 if ( eHAL_STATUS_SUCCESS == halStatus )
1409 {
1410 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1411 {
1412 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1413 rc = wait_for_completion_timeout(
1414 &pAdapter->hdd_get_batch_scan_req_var,
1415 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1416 if (0 == rc)
1417 {
1418 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1419 "%s: Timeout waiting to fetch batch scan rsp from fw",
1420 __func__);
1421 return -EFAULT;
1422 }
1423 }
1424
1425 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
1426 "scancount=%ld\n", pAdapter->numScanList);
1427 pDest += len;
1428 cur_len += len;
1429
1430 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1431 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1432 cur_len, rem_len);
1433 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1434
1435 count = 0;
1436 len = (len - pPrivData->used_len);
1437 pDest = (command + pPrivData->used_len);
1438 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1439 "BATCH SCAN RESULT:");
1440 while(count < len)
1441 {
1442 printk("%c", *(pDest + count));
1443 count++;
1444 }
1445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1446 "%s: copy %d data to user buffer", __func__, len);
1447 if (copy_to_user(pPrivData->buf, pDest, len))
1448 {
1449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1450 "%s: failed to copy data to user buffer", __func__);
1451 return -EFAULT;
1452 }
1453 }
1454 else
1455 {
1456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1457 "sme_GetBatchScanScan returned failure halStatus %d",
1458 halStatus);
1459 return -EINVAL;
1460 }
1461 }
1462 else
1463 {
1464 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1465 "%s: copy %d data to user buffer", __func__, len);
1466 count = 0;
1467 len = (len - pPrivData->used_len);
1468 pDest = (command + pPrivData->used_len);
1469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1470 "BATCH SCAN RESULT:");
1471 while(count < len)
1472 {
1473 printk("%c", *(pDest + count));
1474 count++;
1475 }
1476 if (copy_to_user(pPrivData->buf, pDest, len))
1477 {
1478 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1479 "%s: failed to copy data to user buffer", __func__);
1480 return -EFAULT;
1481 }
1482 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1483 halStatus = sme_TriggerBatchScanResultInd(
1484 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1485 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1486 pAdapter);
1487 if ( eHAL_STATUS_SUCCESS != halStatus )
1488 {
1489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1490 "sme_GetBatchScanScan returned failure halStatus %d",
1491 halStatus);
1492 }
1493 }
1494
1495 return 0;
1496} /*End of hdd_return_batch_scan_rsp_to_user*/
1497
1498#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1499
Jeff Johnson295189b2012-06-20 16:38:30 -07001500int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1501{
1502 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1503 hdd_priv_data_t priv_data;
1504 tANI_U8 *command = NULL;
1505 int ret = 0;
1506
1507 if (NULL == pAdapter)
1508 {
1509 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001510 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001511 ret = -ENODEV;
1512 goto exit;
1513 }
1514
Jeff Johnsone7245742012-09-05 17:12:55 -07001515 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001516 {
1517 ret = -EINVAL;
1518 goto exit;
1519 }
1520
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001521 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1522 {
1523 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1524 "%s:LOGP in Progress. Ignore!!!", __func__);
1525 ret = -EBUSY;
1526 goto exit;
1527 }
1528
Jeff Johnson295189b2012-06-20 16:38:30 -07001529 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1530 {
1531 ret = -EFAULT;
1532 goto exit;
1533 }
1534
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001535 if (priv_data.total_len <= 0)
1536 {
1537 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1538 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1539 priv_data.total_len);
1540 ret = -EINVAL;
1541 goto exit;
1542 }
1543
1544 /* Allocate +1 for '\0' */
1545 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001546 if (!command)
1547 {
1548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001549 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001550 ret = -ENOMEM;
1551 goto exit;
1552 }
1553
1554 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1555 {
1556 ret = -EFAULT;
1557 goto exit;
1558 }
1559
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001560 /* Making sure the command is NUL-terminated */
1561 command[priv_data.total_len] = '\0';
1562
Jeff Johnson295189b2012-06-20 16:38:30 -07001563 if ((SIOCDEVPRIVATE + 1) == cmd)
1564 {
1565 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1566
1567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001568 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001569
1570 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1571 {
1572 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1573 sizeof(tSirMacAddr)))
1574 {
1575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001576 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001577 ret = -EFAULT;
1578 }
1579 }
Amar Singhal0974e402013-02-12 14:27:46 -08001580 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001581 {
Amar Singhal0974e402013-02-12 14:27:46 -08001582 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001583 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001584
Jeff Johnson295189b2012-06-20 16:38:30 -07001585 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001586
1587 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001588 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001589 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001590 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001591 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001592 ret = hdd_setBand_helper(dev, ptr);
1593 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001594 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1595 {
1596 char *country_code;
1597
1598 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001599
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001600 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001601 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301602 hdd_checkandupdate_phymode(pAdapter, country_code);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001603 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1604 (void *)(tSmeChangeCountryCallback)
1605 wlan_hdd_change_country_code_callback,
1606 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1607 if (eHAL_STATUS_SUCCESS == ret)
1608 {
1609 ret = wait_for_completion_interruptible_timeout(
1610 &pAdapter->change_country_code,
1611 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1612 if (0 >= ret)
1613 {
1614 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1615 __func__);
1616 }
1617 }
1618 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001619 {
1620 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001621 "%s: SME Change Country code fail ret=%d", __func__, ret);
1622 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001623 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001624
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001625 }
1626 /*
1627 command should be a string having format
1628 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1629 */
Amar Singhal0974e402013-02-12 14:27:46 -08001630 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001631 {
Amar Singhal0974e402013-02-12 14:27:46 -08001632 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001633
1634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001635 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001636
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001637 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001638 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001639 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1640 {
1641 int suspend = 0;
1642 tANI_U8 *ptr = (tANI_U8*)command + 15;
1643
1644 suspend = *ptr - '0';
1645 hdd_set_wlan_suspend_mode(suspend);
1646 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001647#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1648 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1649 {
1650 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001651 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001652 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1653 eHalStatus status = eHAL_STATUS_SUCCESS;
1654
1655 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1656 value = value + 15;
1657
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001658 /* Convert the value from ascii to integer */
1659 ret = kstrtos8(value, 10, &rssi);
1660 if (ret < 0)
1661 {
1662 /* If the input value is greater than max value of datatype, then also
1663 kstrtou8 fails */
1664 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1665 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
1666 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1667 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1668 ret = -EINVAL;
1669 goto exit;
1670 }
1671
Srinivas Girigowdade697412013-02-14 16:31:48 -08001672 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001673
Srinivas Girigowdade697412013-02-14 16:31:48 -08001674 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1675 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1676 {
1677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1678 "Neighbor lookup threshold value %d is out of range"
1679 " (Min: %d Max: %d)", lookUpThreshold,
1680 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1681 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1682 ret = -EINVAL;
1683 goto exit;
1684 }
1685
1686 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1687 "%s: Received Command to Set Roam trigger"
1688 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1689
1690 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1691 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1692 if (eHAL_STATUS_SUCCESS != status)
1693 {
1694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1695 "%s: Failed to set roam trigger, try again", __func__);
1696 ret = -EPERM;
1697 goto exit;
1698 }
1699
1700 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1701 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1702 }
1703 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1704 {
1705 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1706 int rssi = (-1) * lookUpThreshold;
1707 char extra[32];
1708 tANI_U8 len = 0;
1709
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001710 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001711 if (copy_to_user(priv_data.buf, &extra, len + 1))
1712 {
1713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1714 "%s: failed to copy data to user buffer", __func__);
1715 ret = -EFAULT;
1716 goto exit;
1717 }
1718 }
1719 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1720 {
1721 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001722 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001723 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001724
Srinivas Girigowdade697412013-02-14 16:31:48 -08001725 /* input refresh period is in terms of seconds */
1726 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1727 value = value + 18;
1728 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001729 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001730 if (ret < 0)
1731 {
1732 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001733 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001735 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001736 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001737 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1738 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001739 ret = -EINVAL;
1740 goto exit;
1741 }
1742
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001743 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1744 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001745 {
1746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001747 "Roam scan period value %d is out of range"
1748 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001749 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1750 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001751 ret = -EINVAL;
1752 goto exit;
1753 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001754 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001755
1756 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1757 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001758 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001759
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001760 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1761 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001762 }
1763 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1764 {
1765 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1766 char extra[32];
1767 tANI_U8 len = 0;
1768
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001769 len = scnprintf(extra, sizeof(extra), "%s %d",
1770 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001771 /* Returned value is in units of seconds */
1772 if (copy_to_user(priv_data.buf, &extra, len + 1))
1773 {
1774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1775 "%s: failed to copy data to user buffer", __func__);
1776 ret = -EFAULT;
1777 goto exit;
1778 }
1779 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001780 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1781 {
1782 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001783 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001784 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001785
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001786 /* input refresh period is in terms of seconds */
1787 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1788 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001789
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001790 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001791 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001792 if (ret < 0)
1793 {
1794 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001795 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001797 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001798 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001799 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1800 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1801 ret = -EINVAL;
1802 goto exit;
1803 }
1804
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001805 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1806 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1807 {
1808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1809 "Neighbor scan results refresh period value %d is out of range"
1810 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1811 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1812 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1813 ret = -EINVAL;
1814 goto exit;
1815 }
1816 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1817
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1819 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001820 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001821
1822 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1823 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1824 }
1825 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1826 {
1827 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1828 char extra[32];
1829 tANI_U8 len = 0;
1830
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001831 len = scnprintf(extra, sizeof(extra), "%s %d",
1832 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001833 /* Returned value is in units of seconds */
1834 if (copy_to_user(priv_data.buf, &extra, len + 1))
1835 {
1836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1837 "%s: failed to copy data to user buffer", __func__);
1838 ret = -EFAULT;
1839 goto exit;
1840 }
1841 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001842#ifdef FEATURE_WLAN_LFR
1843 /* SETROAMMODE */
1844 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1845 {
1846 tANI_U8 *value = command;
1847 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1848
1849 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1850 value = value + SIZE_OF_SETROAMMODE + 1;
1851
1852 /* Convert the value from ascii to integer */
1853 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1854 if (ret < 0)
1855 {
1856 /* If the input value is greater than max value of datatype, then also
1857 kstrtou8 fails */
1858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1859 "%s: kstrtou8 failed range [%d - %d]", __func__,
1860 CFG_LFR_FEATURE_ENABLED_MIN,
1861 CFG_LFR_FEATURE_ENABLED_MAX);
1862 ret = -EINVAL;
1863 goto exit;
1864 }
1865 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1866 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1867 {
1868 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1869 "Roam Mode value %d is out of range"
1870 " (Min: %d Max: %d)", roamMode,
1871 CFG_LFR_FEATURE_ENABLED_MIN,
1872 CFG_LFR_FEATURE_ENABLED_MAX);
1873 ret = -EINVAL;
1874 goto exit;
1875 }
1876
1877 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1878 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
1879 /*
1880 * Note that
1881 * SETROAMMODE 0 is to enable LFR while
1882 * SETROAMMODE 1 is to disable LFR, but
1883 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
1884 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
1885 */
1886 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1887 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
1888 else
1889 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
1890
1891 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
1892 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
1893 }
1894 /* GETROAMMODE */
1895 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
1896 {
1897 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1898 char extra[32];
1899 tANI_U8 len = 0;
1900
1901 /*
1902 * roamMode value shall be inverted because the sementics is different.
1903 */
1904 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1905 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
1906 else
1907 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
1908
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001909 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001910 if (copy_to_user(priv_data.buf, &extra, len + 1))
1911 {
1912 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1913 "%s: failed to copy data to user buffer", __func__);
1914 ret = -EFAULT;
1915 goto exit;
1916 }
1917 }
1918#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08001919#endif
1920#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1921 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1922 {
1923 tANI_U8 *value = command;
1924 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1925
1926 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1927 value = value + 13;
1928 /* Convert the value from ascii to integer */
1929 ret = kstrtou8(value, 10, &roamRssiDiff);
1930 if (ret < 0)
1931 {
1932 /* If the input value is greater than max value of datatype, then also
1933 kstrtou8 fails */
1934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1935 "%s: kstrtou8 failed range [%d - %d]", __func__,
1936 CFG_ROAM_RSSI_DIFF_MIN,
1937 CFG_ROAM_RSSI_DIFF_MAX);
1938 ret = -EINVAL;
1939 goto exit;
1940 }
1941
1942 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1943 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1944 {
1945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1946 "Roam rssi diff value %d is out of range"
1947 " (Min: %d Max: %d)", roamRssiDiff,
1948 CFG_ROAM_RSSI_DIFF_MIN,
1949 CFG_ROAM_RSSI_DIFF_MAX);
1950 ret = -EINVAL;
1951 goto exit;
1952 }
1953
1954 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1955 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1956
1957 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1958 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1959 }
1960 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1961 {
1962 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1963 char extra[32];
1964 tANI_U8 len = 0;
1965
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001966 len = scnprintf(extra, sizeof(extra), "%s %d",
1967 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001968 if (copy_to_user(priv_data.buf, &extra, len + 1))
1969 {
1970 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1971 "%s: failed to copy data to user buffer", __func__);
1972 ret = -EFAULT;
1973 goto exit;
1974 }
1975 }
1976#endif
1977#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1978 else if (strncmp(command, "GETBAND", 7) == 0)
1979 {
1980 int band = -1;
1981 char extra[32];
1982 tANI_U8 len = 0;
1983 hdd_getBand_helper(pHddCtx, &band);
1984
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001985 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001986 if (copy_to_user(priv_data.buf, &extra, len + 1))
1987 {
1988 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1989 "%s: failed to copy data to user buffer", __func__);
1990 ret = -EFAULT;
1991 goto exit;
1992 }
1993 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001994 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
1995 {
1996 tANI_U8 *value = command;
1997 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
1998 tANI_U8 numChannels = 0;
1999 eHalStatus status = eHAL_STATUS_SUCCESS;
2000
2001 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2002 if (eHAL_STATUS_SUCCESS != status)
2003 {
2004 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2005 "%s: Failed to parse channel list information", __func__);
2006 ret = -EINVAL;
2007 goto exit;
2008 }
2009
2010 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2011 {
2012 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2013 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2014 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2015 ret = -EINVAL;
2016 goto exit;
2017 }
2018 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2019 numChannels);
2020 if (eHAL_STATUS_SUCCESS != status)
2021 {
2022 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2023 "%s: Failed to update channel list information", __func__);
2024 ret = -EINVAL;
2025 goto exit;
2026 }
2027 }
2028 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2029 {
2030 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2031 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002032 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002033 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002034 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002035
2036 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2037 ChannelList, &numChannels ))
2038 {
2039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2040 "%s: failed to get roam scan channel list", __func__);
2041 ret = -EFAULT;
2042 goto exit;
2043 }
2044 /* output channel list is of the format
2045 [Number of roam scan channels][Channel1][Channel2]... */
2046 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002047 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002048 for (j = 0; (j < numChannels); j++)
2049 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002050 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2051 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002052 }
2053
2054 if (copy_to_user(priv_data.buf, &extra, len + 1))
2055 {
2056 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2057 "%s: failed to copy data to user buffer", __func__);
2058 ret = -EFAULT;
2059 goto exit;
2060 }
2061 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002062 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2063 {
2064 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2065 char extra[32];
2066 tANI_U8 len = 0;
2067
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002068 /* Check if the features OKC/CCX/11R are supported simultaneously,
2069 then this operation is not permitted (return FAILURE) */
2070 if (ccxMode &&
2071 hdd_is_okc_mode_enabled(pHddCtx) &&
2072 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2073 {
2074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2075 "%s: OKC/CCX/11R are supported simultaneously"
2076 " hence this operation is not permitted!", __func__);
2077 ret = -EPERM;
2078 goto exit;
2079 }
2080
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002081 len = scnprintf(extra, sizeof(extra), "%s %d",
2082 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002083 if (copy_to_user(priv_data.buf, &extra, len + 1))
2084 {
2085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2086 "%s: failed to copy data to user buffer", __func__);
2087 ret = -EFAULT;
2088 goto exit;
2089 }
2090 }
2091 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2092 {
2093 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2094 char extra[32];
2095 tANI_U8 len = 0;
2096
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002097 /* Check if the features OKC/CCX/11R are supported simultaneously,
2098 then this operation is not permitted (return FAILURE) */
2099 if (okcMode &&
2100 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2101 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2102 {
2103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2104 "%s: OKC/CCX/11R are supported simultaneously"
2105 " hence this operation is not permitted!", __func__);
2106 ret = -EPERM;
2107 goto exit;
2108 }
2109
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002110 len = scnprintf(extra, sizeof(extra), "%s %d",
2111 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002112 if (copy_to_user(priv_data.buf, &extra, len + 1))
2113 {
2114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2115 "%s: failed to copy data to user buffer", __func__);
2116 ret = -EFAULT;
2117 goto exit;
2118 }
2119 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002120 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002121 {
2122 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2123 char extra[32];
2124 tANI_U8 len = 0;
2125
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002126 len = scnprintf(extra, sizeof(extra), "%s %d",
2127 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002128 if (copy_to_user(priv_data.buf, &extra, len + 1))
2129 {
2130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2131 "%s: failed to copy data to user buffer", __func__);
2132 ret = -EFAULT;
2133 goto exit;
2134 }
2135 }
2136 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2137 {
2138 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2139 char extra[32];
2140 tANI_U8 len = 0;
2141
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002142 len = scnprintf(extra, sizeof(extra), "%s %d",
2143 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002144 if (copy_to_user(priv_data.buf, &extra, len + 1))
2145 {
2146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2147 "%s: failed to copy data to user buffer", __func__);
2148 ret = -EFAULT;
2149 goto exit;
2150 }
2151 }
2152 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2153 {
2154 tANI_U8 *value = command;
2155 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2156
2157 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2158 value = value + 26;
2159 /* Convert the value from ascii to integer */
2160 ret = kstrtou8(value, 10, &minTime);
2161 if (ret < 0)
2162 {
2163 /* If the input value is greater than max value of datatype, then also
2164 kstrtou8 fails */
2165 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2166 "%s: kstrtou8 failed range [%d - %d]", __func__,
2167 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2168 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2169 ret = -EINVAL;
2170 goto exit;
2171 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002172 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2173 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2174 {
2175 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2176 "scan min channel time value %d is out of range"
2177 " (Min: %d Max: %d)", minTime,
2178 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2179 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2180 ret = -EINVAL;
2181 goto exit;
2182 }
2183
2184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2185 "%s: Received Command to change channel min time = %d", __func__, minTime);
2186
2187 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2188 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2189 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002190 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2191 {
2192 tANI_U8 *value = command;
2193 tANI_U8 channel = 0;
2194 tANI_U8 dwellTime = 0;
2195 tANI_U8 bufLen = 0;
2196 tANI_U8 *buf = NULL;
2197 tSirMacAddr targetApBssid;
2198 eHalStatus status = eHAL_STATUS_SUCCESS;
2199 struct ieee80211_channel chan;
2200 tANI_U8 finalLen = 0;
2201 tANI_U8 *finalBuf = NULL;
2202 tANI_U8 temp = 0;
2203 u64 cookie;
2204 hdd_station_ctx_t *pHddStaCtx = NULL;
2205 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2206
2207 /* if not associated, no need to send action frame */
2208 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2209 {
2210 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2211 ret = -EINVAL;
2212 goto exit;
2213 }
2214
2215 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2216 &dwellTime, &buf, &bufLen);
2217 if (eHAL_STATUS_SUCCESS != status)
2218 {
2219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2220 "%s: Failed to parse send action frame data", __func__);
2221 ret = -EINVAL;
2222 goto exit;
2223 }
2224
2225 /* if the target bssid is different from currently associated AP,
2226 then no need to send action frame */
2227 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2228 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2229 {
2230 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2231 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002232 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002233 goto exit;
2234 }
2235
2236 /* if the channel number is different from operating channel then
2237 no need to send action frame */
2238 if (channel != pHddStaCtx->conn_info.operationChannel)
2239 {
2240 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2241 "%s: channel(%d) is different from operating channel(%d)",
2242 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2243 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002244 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002245 goto exit;
2246 }
2247 chan.center_freq = sme_ChnToFreq(channel);
2248
2249 finalLen = bufLen + 24;
2250 finalBuf = vos_mem_malloc(finalLen);
2251 if (NULL == finalBuf)
2252 {
2253 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2254 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002255 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002256 goto exit;
2257 }
2258 vos_mem_zero(finalBuf, finalLen);
2259
2260 /* Fill subtype */
2261 temp = SIR_MAC_MGMT_ACTION << 4;
2262 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2263
2264 /* Fill type */
2265 temp = SIR_MAC_MGMT_FRAME;
2266 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2267
2268 /* Fill destination address (bssid of the AP) */
2269 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2270
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002271 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002272 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2273
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002274 /* Fill BSSID (AP mac address) */
2275 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002276
2277 /* Fill received buffer from 24th address */
2278 vos_mem_copy(finalBuf + 24, buf, bufLen);
2279
Jeff Johnson11c33152013-04-16 17:52:40 -07002280 /* done with the parsed buffer */
2281 vos_mem_free(buf);
2282
Yue Maf49ba872013-08-19 12:04:25 -07002283 wlan_hdd_action( NULL,
2284#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2285 &(pAdapter->wdev),
2286#else
2287 dev,
2288#endif
2289 &chan, 0,
2290#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2291 NL80211_CHAN_HT20, 1,
2292#endif
2293 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002294 1, &cookie );
2295 vos_mem_free(finalBuf);
2296 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002297 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2298 {
2299 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2300 char extra[32];
2301 tANI_U8 len = 0;
2302
2303 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002304 len = scnprintf(extra, sizeof(extra), "%s %d",
2305 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002306 if (copy_to_user(priv_data.buf, &extra, len + 1))
2307 {
2308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2309 "%s: failed to copy data to user buffer", __func__);
2310 ret = -EFAULT;
2311 goto exit;
2312 }
2313 }
2314 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2315 {
2316 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002317 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002318 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002319
2320 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2321 value = value + 19;
2322 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002323 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002324 if (ret < 0)
2325 {
2326 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002327 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002328 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002329 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002330 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2331 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2332 ret = -EINVAL;
2333 goto exit;
2334 }
2335
2336 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2337 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2338 {
2339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2340 "lfr mode value %d is out of range"
2341 " (Min: %d Max: %d)", maxTime,
2342 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2343 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2344 ret = -EINVAL;
2345 goto exit;
2346 }
2347
2348 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2349 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2350
2351 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002352
2353 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2354 * where RFS is the RF Switching time. It is twice RFS to consider the
2355 * time to go off channel and return to the home channel. */
2356 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2357 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2358 {
2359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2360 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
2361 " Hence enforcing home away time to disable (0)",
2362 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2363 homeAwayTime = 0;
2364 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2365 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2366 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002367 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2368 }
2369 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2370 {
2371 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2372 char extra[32];
2373 tANI_U8 len = 0;
2374
2375 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002376 len = scnprintf(extra, sizeof(extra), "%s %d",
2377 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002378 if (copy_to_user(priv_data.buf, &extra, len + 1))
2379 {
2380 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2381 "%s: failed to copy data to user buffer", __func__);
2382 ret = -EFAULT;
2383 goto exit;
2384 }
2385 }
2386 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2387 {
2388 tANI_U8 *value = command;
2389 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2390
2391 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2392 value = value + 16;
2393 /* Convert the value from ascii to integer */
2394 ret = kstrtou16(value, 10, &val);
2395 if (ret < 0)
2396 {
2397 /* If the input value is greater than max value of datatype, then also
2398 kstrtou16 fails */
2399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2400 "%s: kstrtou16 failed range [%d - %d]", __func__,
2401 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2402 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2403 ret = -EINVAL;
2404 goto exit;
2405 }
2406
2407 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2408 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2409 {
2410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2411 "scan home time value %d is out of range"
2412 " (Min: %d Max: %d)", val,
2413 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2414 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2415 ret = -EINVAL;
2416 goto exit;
2417 }
2418
2419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2420 "%s: Received Command to change scan home time = %d", __func__, val);
2421
2422 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2423 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2424 }
2425 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2426 {
2427 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2428 char extra[32];
2429 tANI_U8 len = 0;
2430
2431 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002432 len = scnprintf(extra, sizeof(extra), "%s %d",
2433 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002434 if (copy_to_user(priv_data.buf, &extra, len + 1))
2435 {
2436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2437 "%s: failed to copy data to user buffer", __func__);
2438 ret = -EFAULT;
2439 goto exit;
2440 }
2441 }
2442 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2443 {
2444 tANI_U8 *value = command;
2445 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2446
2447 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2448 value = value + 17;
2449 /* Convert the value from ascii to integer */
2450 ret = kstrtou8(value, 10, &val);
2451 if (ret < 0)
2452 {
2453 /* If the input value is greater than max value of datatype, then also
2454 kstrtou8 fails */
2455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2456 "%s: kstrtou8 failed range [%d - %d]", __func__,
2457 CFG_ROAM_INTRA_BAND_MIN,
2458 CFG_ROAM_INTRA_BAND_MAX);
2459 ret = -EINVAL;
2460 goto exit;
2461 }
2462
2463 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2464 (val > CFG_ROAM_INTRA_BAND_MAX))
2465 {
2466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2467 "intra band mode value %d is out of range"
2468 " (Min: %d Max: %d)", val,
2469 CFG_ROAM_INTRA_BAND_MIN,
2470 CFG_ROAM_INTRA_BAND_MAX);
2471 ret = -EINVAL;
2472 goto exit;
2473 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2475 "%s: Received Command to change intra band = %d", __func__, val);
2476
2477 pHddCtx->cfg_ini->nRoamIntraBand = val;
2478 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2479 }
2480 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2481 {
2482 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2483 char extra[32];
2484 tANI_U8 len = 0;
2485
2486 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002487 len = scnprintf(extra, sizeof(extra), "%s %d",
2488 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002489 if (copy_to_user(priv_data.buf, &extra, len + 1))
2490 {
2491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2492 "%s: failed to copy data to user buffer", __func__);
2493 ret = -EFAULT;
2494 goto exit;
2495 }
2496 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002497 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2498 {
2499 tANI_U8 *value = command;
2500 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2501
2502 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2503 value = value + 15;
2504 /* Convert the value from ascii to integer */
2505 ret = kstrtou8(value, 10, &nProbes);
2506 if (ret < 0)
2507 {
2508 /* If the input value is greater than max value of datatype, then also
2509 kstrtou8 fails */
2510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2511 "%s: kstrtou8 failed range [%d - %d]", __func__,
2512 CFG_ROAM_SCAN_N_PROBES_MIN,
2513 CFG_ROAM_SCAN_N_PROBES_MAX);
2514 ret = -EINVAL;
2515 goto exit;
2516 }
2517
2518 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2519 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2520 {
2521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2522 "NProbes value %d is out of range"
2523 " (Min: %d Max: %d)", nProbes,
2524 CFG_ROAM_SCAN_N_PROBES_MIN,
2525 CFG_ROAM_SCAN_N_PROBES_MAX);
2526 ret = -EINVAL;
2527 goto exit;
2528 }
2529
2530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2531 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2532
2533 pHddCtx->cfg_ini->nProbes = nProbes;
2534 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2535 }
2536 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2537 {
2538 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2539 char extra[32];
2540 tANI_U8 len = 0;
2541
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002542 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002543 if (copy_to_user(priv_data.buf, &extra, len + 1))
2544 {
2545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2546 "%s: failed to copy data to user buffer", __func__);
2547 ret = -EFAULT;
2548 goto exit;
2549 }
2550 }
2551 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2552 {
2553 tANI_U8 *value = command;
2554 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002555 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002556
2557 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2558 /* input value is in units of msec */
2559 value = value + 20;
2560 /* Convert the value from ascii to integer */
2561 ret = kstrtou16(value, 10, &homeAwayTime);
2562 if (ret < 0)
2563 {
2564 /* If the input value is greater than max value of datatype, then also
2565 kstrtou8 fails */
2566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2567 "%s: kstrtou8 failed range [%d - %d]", __func__,
2568 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2569 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2570 ret = -EINVAL;
2571 goto exit;
2572 }
2573
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002574 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2575 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2576 {
2577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2578 "homeAwayTime value %d is out of range"
2579 " (Min: %d Max: %d)", homeAwayTime,
2580 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2581 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2582 ret = -EINVAL;
2583 goto exit;
2584 }
2585
2586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2587 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2588
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002589 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2590 * where RFS is the RF Switching time. It is twice RFS to consider the
2591 * time to go off channel and return to the home channel. */
2592 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2593 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2594 {
2595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2596 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
2597 " Hence enforcing home away time to disable (0)",
2598 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2599 homeAwayTime = 0;
2600 }
2601
2602 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2603 {
2604 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2605 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2606 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002607 }
2608 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2609 {
2610 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2611 char extra[32];
2612 tANI_U8 len = 0;
2613
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002614 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002615 if (copy_to_user(priv_data.buf, &extra, len + 1))
2616 {
2617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2618 "%s: failed to copy data to user buffer", __func__);
2619 ret = -EFAULT;
2620 goto exit;
2621 }
2622 }
2623 else if (strncmp(command, "REASSOC", 7) == 0)
2624 {
2625 tANI_U8 *value = command;
2626 tANI_U8 channel = 0;
2627 tSirMacAddr targetApBssid;
2628 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002629#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2630 tCsrHandoffRequest handoffInfo;
2631#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002632 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002633 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2634
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002635 /* if not associated, no need to proceed with reassoc */
2636 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2637 {
2638 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2639 ret = -EINVAL;
2640 goto exit;
2641 }
2642
2643 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2644 if (eHAL_STATUS_SUCCESS != status)
2645 {
2646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2647 "%s: Failed to parse reassoc command data", __func__);
2648 ret = -EINVAL;
2649 goto exit;
2650 }
2651
2652 /* if the target bssid is same as currently associated AP,
2653 then no need to proceed with reassoc */
2654 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2655 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2656 {
2657 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2658 ret = -EINVAL;
2659 goto exit;
2660 }
2661
2662 /* Check channel number is a valid channel number */
2663 if(VOS_STATUS_SUCCESS !=
2664 wlan_hdd_validate_operation_channel(pAdapter, channel))
2665 {
2666 hddLog(VOS_TRACE_LEVEL_ERROR,
2667 "%s: Invalid Channel [%d] \n", __func__, channel);
2668 return -EINVAL;
2669 }
2670
2671 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002672#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2673 handoffInfo.channel = channel;
2674 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2675 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2676#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002677 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002678#endif
2679#ifdef FEATURE_WLAN_LFR
2680 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2681 {
2682 tANI_U8 *value = command;
2683 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2684
2685 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2686 value = value + 12;
2687 /* Convert the value from ascii to integer */
2688 ret = kstrtou8(value, 10, &lfrMode);
2689 if (ret < 0)
2690 {
2691 /* If the input value is greater than max value of datatype, then also
2692 kstrtou8 fails */
2693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2694 "%s: kstrtou8 failed range [%d - %d]", __func__,
2695 CFG_LFR_FEATURE_ENABLED_MIN,
2696 CFG_LFR_FEATURE_ENABLED_MAX);
2697 ret = -EINVAL;
2698 goto exit;
2699 }
2700
2701 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2702 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2703 {
2704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2705 "lfr mode value %d is out of range"
2706 " (Min: %d Max: %d)", lfrMode,
2707 CFG_LFR_FEATURE_ENABLED_MIN,
2708 CFG_LFR_FEATURE_ENABLED_MAX);
2709 ret = -EINVAL;
2710 goto exit;
2711 }
2712
2713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2714 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2715
2716 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2717 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2718 }
2719#endif
2720#ifdef WLAN_FEATURE_VOWIFI_11R
2721 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2722 {
2723 tANI_U8 *value = command;
2724 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2725
2726 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2727 value = value + 18;
2728 /* Convert the value from ascii to integer */
2729 ret = kstrtou8(value, 10, &ft);
2730 if (ret < 0)
2731 {
2732 /* If the input value is greater than max value of datatype, then also
2733 kstrtou8 fails */
2734 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2735 "%s: kstrtou8 failed range [%d - %d]", __func__,
2736 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2737 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2738 ret = -EINVAL;
2739 goto exit;
2740 }
2741
2742 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2743 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2744 {
2745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2746 "ft mode value %d is out of range"
2747 " (Min: %d Max: %d)", ft,
2748 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2749 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2750 ret = -EINVAL;
2751 goto exit;
2752 }
2753
2754 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2755 "%s: Received Command to change ft mode = %d", __func__, ft);
2756
2757 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2758 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2759 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302760
2761 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2762 {
2763 tANI_U8 *value = command;
2764 tSirMacAddr targetApBssid;
2765 tANI_U8 trigger = 0;
2766 eHalStatus status = eHAL_STATUS_SUCCESS;
2767 hdd_station_ctx_t *pHddStaCtx = NULL;
2768 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2769
2770 /* if not associated, no need to proceed with reassoc */
2771 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2772 {
2773 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2774 ret = -EINVAL;
2775 goto exit;
2776 }
2777
2778 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2779 if (eHAL_STATUS_SUCCESS != status)
2780 {
2781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2782 "%s: Failed to parse reassoc command data", __func__);
2783 ret = -EINVAL;
2784 goto exit;
2785 }
2786
2787 /* if the target bssid is same as currently associated AP,
2788 then no need to proceed with reassoc */
2789 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2790 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2791 {
2792 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2793 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2794 __func__);
2795 ret = -EINVAL;
2796 goto exit;
2797 }
2798
2799 /* Proceed with scan/roam */
2800 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2801 &targetApBssid[0],
2802 (tSmeFastRoamTrigger)(trigger));
2803 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002804#endif
2805#ifdef FEATURE_WLAN_CCX
2806 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2807 {
2808 tANI_U8 *value = command;
2809 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2810
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002811 /* Check if the features OKC/CCX/11R are supported simultaneously,
2812 then this operation is not permitted (return FAILURE) */
2813 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2814 hdd_is_okc_mode_enabled(pHddCtx) &&
2815 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2816 {
2817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2818 "%s: OKC/CCX/11R are supported simultaneously"
2819 " hence this operation is not permitted!", __func__);
2820 ret = -EPERM;
2821 goto exit;
2822 }
2823
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002824 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2825 value = value + 11;
2826 /* Convert the value from ascii to integer */
2827 ret = kstrtou8(value, 10, &ccxMode);
2828 if (ret < 0)
2829 {
2830 /* If the input value is greater than max value of datatype, then also
2831 kstrtou8 fails */
2832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2833 "%s: kstrtou8 failed range [%d - %d]", __func__,
2834 CFG_CCX_FEATURE_ENABLED_MIN,
2835 CFG_CCX_FEATURE_ENABLED_MAX);
2836 ret = -EINVAL;
2837 goto exit;
2838 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002839 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2840 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2841 {
2842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2843 "Ccx mode value %d is out of range"
2844 " (Min: %d Max: %d)", ccxMode,
2845 CFG_CCX_FEATURE_ENABLED_MIN,
2846 CFG_CCX_FEATURE_ENABLED_MAX);
2847 ret = -EINVAL;
2848 goto exit;
2849 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002850 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2851 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
2852
2853 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
2854 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
2855 }
2856#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002857 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
2858 {
2859 tANI_U8 *value = command;
2860 tANI_BOOLEAN roamScanControl = 0;
2861
2862 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
2863 value = value + 19;
2864 /* Convert the value from ascii to integer */
2865 ret = kstrtou8(value, 10, &roamScanControl);
2866 if (ret < 0)
2867 {
2868 /* If the input value is greater than max value of datatype, then also
2869 kstrtou8 fails */
2870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2871 "%s: kstrtou8 failed ", __func__);
2872 ret = -EINVAL;
2873 goto exit;
2874 }
2875
2876 if (0 != roamScanControl)
2877 {
2878 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2879 "roam scan control invalid value = %d",
2880 roamScanControl);
2881 ret = -EINVAL;
2882 goto exit;
2883 }
2884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2885 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
2886
2887 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
2888 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002889#ifdef FEATURE_WLAN_OKC
2890 else if (strncmp(command, "SETOKCMODE", 10) == 0)
2891 {
2892 tANI_U8 *value = command;
2893 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
2894
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002895 /* Check if the features OKC/CCX/11R are supported simultaneously,
2896 then this operation is not permitted (return FAILURE) */
2897 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2898 hdd_is_okc_mode_enabled(pHddCtx) &&
2899 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2900 {
2901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2902 "%s: OKC/CCX/11R are supported simultaneously"
2903 " hence this operation is not permitted!", __func__);
2904 ret = -EPERM;
2905 goto exit;
2906 }
2907
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002908 /* Move pointer to ahead of SETOKCMODE<delimiter> */
2909 value = value + 11;
2910 /* Convert the value from ascii to integer */
2911 ret = kstrtou8(value, 10, &okcMode);
2912 if (ret < 0)
2913 {
2914 /* If the input value is greater than max value of datatype, then also
2915 kstrtou8 fails */
2916 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2917 "%s: kstrtou8 failed range [%d - %d]", __func__,
2918 CFG_OKC_FEATURE_ENABLED_MIN,
2919 CFG_OKC_FEATURE_ENABLED_MAX);
2920 ret = -EINVAL;
2921 goto exit;
2922 }
2923
2924 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
2925 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
2926 {
2927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2928 "Okc mode value %d is out of range"
2929 " (Min: %d Max: %d)", okcMode,
2930 CFG_OKC_FEATURE_ENABLED_MIN,
2931 CFG_OKC_FEATURE_ENABLED_MAX);
2932 ret = -EINVAL;
2933 goto exit;
2934 }
2935
2936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2937 "%s: Received Command to change okc mode = %d", __func__, okcMode);
2938
2939 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
2940 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002941 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
2942 {
2943 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
2944 char extra[32];
2945 tANI_U8 len = 0;
2946
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002947 len = scnprintf(extra, sizeof(extra), "%s %d",
2948 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002949 if (copy_to_user(priv_data.buf, &extra, len + 1))
2950 {
2951 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2952 "%s: failed to copy data to user buffer", __func__);
2953 ret = -EFAULT;
2954 goto exit;
2955 }
2956 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002957#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302958#ifdef WLAN_FEATURE_PACKET_FILTERING
2959 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2960 {
2961 tANI_U8 filterType = 0;
2962 tANI_U8 *value = command;
2963
2964 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2965 value = value + 22;
2966
2967 /* Convert the value from ascii to integer */
2968 ret = kstrtou8(value, 10, &filterType);
2969 if (ret < 0)
2970 {
2971 /* If the input value is greater than max value of datatype,
2972 * then also kstrtou8 fails
2973 */
2974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2975 "%s: kstrtou8 failed range ", __func__);
2976 ret = -EINVAL;
2977 goto exit;
2978 }
2979
2980 if (filterType != 0 && filterType != 1)
2981 {
2982 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2983 "%s: Accepted Values are 0 and 1 ", __func__);
2984 ret = -EINVAL;
2985 goto exit;
2986 }
2987 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2988 pAdapter->sessionId);
2989 }
2990#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05302991 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
2992 {
2993 char *dhcpPhase;
2994 dhcpPhase = command + 12;
2995 if ('1' == *dhcpPhase)
2996 {
2997 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
2998 pAdapter->macAddressCurrent.bytes);
2999 }
3000 else if ('2' == *dhcpPhase)
3001 {
3002 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3003 pAdapter->macAddressCurrent.bytes);
3004 }
3005 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003006 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3007 {
3008 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3009 }
3010 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3011 {
3012 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3013 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303014 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3015 {
3016 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3017 char extra[32];
3018 tANI_U8 len = 0;
3019
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003020 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303021 (int)pCfg->nActiveMaxChnTime);
3022 if (copy_to_user(priv_data.buf, &extra, len + 1))
3023 {
3024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3025 "%s: failed to copy data to user buffer", __func__);
3026 ret = -EFAULT;
3027 goto exit;
3028 }
3029 ret = len;
3030 }
3031 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3032 {
3033 tANI_U8 *value = command;
3034 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3035 int val = 0, temp;
3036
3037 value = value + 13;
3038 temp = kstrtou32(value, 10, &val);
3039 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3040 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3041 {
3042 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3043 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3044 ret = -EFAULT;
3045 goto exit;
3046 }
3047 pCfg->nActiveMaxChnTime = val;
3048 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003049 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3050 {
3051 tANI_U8 filterType = 0;
3052 tANI_U8 *value;
3053 value = command + 9;
3054
3055 /* Convert the value from ascii to integer */
3056 ret = kstrtou8(value, 10, &filterType);
3057 if (ret < 0)
3058 {
3059 /* If the input value is greater than max value of datatype,
3060 * then also kstrtou8 fails
3061 */
3062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3063 "%s: kstrtou8 failed range ", __func__);
3064 ret = -EINVAL;
3065 goto exit;
3066 }
3067 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3068 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3069 {
3070 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3071 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3072 " 2-Sink ", __func__);
3073 ret = -EINVAL;
3074 goto exit;
3075 }
3076 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3077 pHddCtx->drvr_miracast = filterType;
3078 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3079 }
Leo Chang614d2072013-08-22 14:59:44 -07003080 else if (strncmp(command, "SETMCRATE", 9) == 0)
3081 {
3082 int rc;
3083 tANI_U8 *value = command;
3084 int targetRate;
3085
3086 /* Only valid for SAP mode */
3087 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3088 {
3089 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3090 "%s: SAP mode is not running", __func__);
3091 ret = -EFAULT;
3092 goto exit;
3093 }
3094
3095 /* Move pointer to ahead of SETMCRATE<delimiter> */
3096 /* input value is in units of hundred kbps */
3097 value = value + 10;
3098 /* Convert the value from ascii to integer, decimal base */
3099 ret = kstrtouint(value, 10, &targetRate);
3100
3101 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
3102 if (rc)
3103 {
3104 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3105 "%s: Set MC Rate Fail %d", __func__, rc);
3106 ret = -EFAULT;
3107 goto exit;
3108 }
3109 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303110#ifdef FEATURE_WLAN_BATCH_SCAN
3111 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3112 {
3113 char extra[32];
3114 tANI_U8 len = 0;
3115 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3116
3117 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3118 {
3119 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3120 "%s: Batch scan feature is not supported by FW", __func__);
3121 ret = -EINVAL;
3122 goto exit;
3123 }
3124
3125 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3126 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3127 {
3128 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3129 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3130 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3131 " mode",
3132 pAdapter->device_mode);
3133 ret = -EINVAL;
3134 goto exit;
3135 }
3136
3137 len = snprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
3138 version);
3139 if (copy_to_user(priv_data.buf, &extra, len + 1))
3140 {
3141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3142 "%s: failed to copy data to user buffer", __func__);
3143 ret = -EFAULT;
3144 goto exit;
3145 }
3146 ret = HDD_BATCH_SCAN_VERSION;
3147 }
3148 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3149 {
3150 int status;
3151 tANI_U8 *value = (command + 16);
3152 eHalStatus halStatus;
3153 unsigned long rc;
3154 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3155 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3156
3157 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3158 {
3159 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3160 "%s: Batch scan feature is not supported by FW", __func__);
3161 ret = -EINVAL;
3162 goto exit;
3163 }
3164
Rajeev Kumar20140c12013-10-21 19:39:02 -07003165
Rajeev79dbe4c2013-10-05 11:03:42 +05303166 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3167 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3168 {
3169 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003170 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303171 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3172 pAdapter->device_mode);
3173 ret = -EINVAL;
3174 goto exit;
3175 }
3176
Rajeev Kumar20140c12013-10-21 19:39:02 -07003177
Rajeev79dbe4c2013-10-05 11:03:42 +05303178 status = hdd_parse_set_batchscan_command(value, pReq);
3179 if (status)
3180 {
3181 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003182 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303183 ret = -EINVAL;
3184 goto exit;
3185 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003186
3187
Rajeev79dbe4c2013-10-05 11:03:42 +05303188 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3189 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3190 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3191 pAdapter);
3192
3193 if ( eHAL_STATUS_SUCCESS == halStatus )
3194 {
3195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3196 "sme_SetBatchScanReq returned success halStatus %d",
3197 halStatus);
3198 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3199 {
3200 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3201 rc = wait_for_completion_timeout(
3202 &pAdapter->hdd_set_batch_scan_req_var,
3203 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3204 if (0 == rc)
3205 {
3206 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3207 "%s: Timeout waiting for set batch scan to complete",
3208 __func__);
3209 ret = -EINVAL;
3210 goto exit;
3211 }
3212 }
3213 if ( !pRsp->nScansToBatch )
3214 {
3215 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3216 "%s: Received set batch scan failure response from FW",
3217 __func__, pRsp->nScansToBatch);
3218 ret = -EINVAL;
3219 goto exit;
3220 }
3221 /*As per the Batch Scan Framework API we should return the MIN of
3222 either MSCAN or the max # of scans firmware can cache*/
3223 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3224
Rajeev Kumar20140c12013-10-21 19:39:02 -07003225 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3226
Rajeev79dbe4c2013-10-05 11:03:42 +05303227 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3228 "%s: request MSCAN %d response MSCAN %d ret %d",
3229 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3230 }
3231 else
3232 {
3233 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3234 "sme_SetBatchScanReq returned failure halStatus %d",
3235 halStatus);
3236 ret = -EINVAL;
3237 goto exit;
3238 }
3239 }
3240 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3241 {
3242 eHalStatus halStatus;
3243 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3244 pInd->param = 0;
3245
3246 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3247 {
3248 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3249 "%s: Batch scan feature is not supported by FW", __func__);
3250 ret = -EINVAL;
3251 goto exit;
3252 }
3253
Rajeev Kumar20140c12013-10-21 19:39:02 -07003254 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303255 {
3256 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003257 "Batch scan is not yet enabled batch scan state %d",
3258 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303259 ret = -EINVAL;
3260 goto exit;
3261 }
3262
Rajeev Kumar20140c12013-10-21 19:39:02 -07003263 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3264
Rajeev79dbe4c2013-10-05 11:03:42 +05303265 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3266 pAdapter->sessionId);
3267 if ( eHAL_STATUS_SUCCESS == halStatus )
3268 {
3269 ret = 0;
3270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3271 "sme_StopBatchScanInd returned success halStatus %d",
3272 halStatus);
3273 }
3274 else
3275 {
3276 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3277 "sme_StopBatchScanInd returned failure halStatus %d",
3278 halStatus);
3279 ret = -EINVAL;
3280 goto exit;
3281 }
3282 }
3283 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3284 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003285 tANI_U32 remain_len;
3286
Rajeev79dbe4c2013-10-05 11:03:42 +05303287 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3288 {
3289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3290 "%s: Batch scan feature is not supported by FW", __func__);
3291 ret = -EINVAL;
3292 goto exit;
3293 }
3294
Rajeev Kumar20140c12013-10-21 19:39:02 -07003295 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303296 {
3297 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003298 "Batch scan is not yet enabled could not return results"
3299 "Batch Scan state %d",
3300 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303301 ret = -EINVAL;
3302 goto exit;
3303 }
3304
3305 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003306 remain_len = priv_data.total_len - priv_data.used_len;
3307 if (remain_len < priv_data.total_len)
3308 {
3309 /*Clear previous batch scan response data if any*/
3310 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3311 }
3312 else
3313 {
3314 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3315 "Invalid total length from user space can't fetch batch"
3316 " scan response total_len %ld used_len %ld remain len %ld",
3317 priv_data.total_len, priv_data.used_len, remain_len);
3318 ret = -EINVAL;
3319 goto exit;
3320 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303321 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3322 }
3323#endif
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003324 else {
3325 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3326 __func__, command);
3327 }
3328
Jeff Johnson295189b2012-06-20 16:38:30 -07003329 }
3330exit:
3331 if (command)
3332 {
3333 kfree(command);
3334 }
3335 return ret;
3336}
3337
Srinivas Girigowdade697412013-02-14 16:31:48 -08003338#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3339void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3340{
3341 eCsrBand band = -1;
3342 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3343 switch (band)
3344 {
3345 case eCSR_BAND_ALL:
3346 *pBand = WLAN_HDD_UI_BAND_AUTO;
3347 break;
3348
3349 case eCSR_BAND_24:
3350 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3351 break;
3352
3353 case eCSR_BAND_5G:
3354 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3355 break;
3356
3357 default:
3358 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3359 *pBand = -1;
3360 break;
3361 }
3362}
3363
3364/**---------------------------------------------------------------------------
3365
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003366 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3367
3368 This function parses the send action frame data passed in the format
3369 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3370
Srinivas Girigowda56076852013-08-20 14:00:50 -07003371 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003372 \param - pTargetApBssid Pointer to target Ap bssid
3373 \param - pChannel Pointer to the Target AP channel
3374 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3375 \param - pBuf Pointer to data
3376 \param - pBufLen Pointer to data length
3377
3378 \return - 0 for success non-zero for failure
3379
3380 --------------------------------------------------------------------------*/
3381VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3382 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3383{
3384 tANI_U8 *inPtr = pValue;
3385 tANI_U8 *dataEnd;
3386 int tempInt;
3387 int j = 0;
3388 int i = 0;
3389 int v = 0;
3390 tANI_U8 tempBuf[32];
3391 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003392 /* 12 hexa decimal digits and 5 ':' */
3393 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003394
3395 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3396 /*no argument after the command*/
3397 if (NULL == inPtr)
3398 {
3399 return -EINVAL;
3400 }
3401
3402 /*no space after the command*/
3403 else if (SPACE_ASCII_VALUE != *inPtr)
3404 {
3405 return -EINVAL;
3406 }
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
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003417 v = sscanf(inPtr, "%17s", macAddress);
3418 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003419 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003420 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3421 "Invalid MAC address or All hex inputs are not read (%d)", v);
3422 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003423 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003424
3425 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3426 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3427 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3428 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3429 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3430 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003431
3432 /* point to the next argument */
3433 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3434 /*no argument after the command*/
3435 if (NULL == inPtr) return -EINVAL;
3436
3437 /*removing empty spaces*/
3438 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3439
3440 /*no argument followed by spaces*/
3441 if ('\0' == *inPtr)
3442 {
3443 return -EINVAL;
3444 }
3445
3446 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003447 v = sscanf(inPtr, "%32s ", tempBuf);
3448 if (1 != v) return -EINVAL;
3449
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003450 v = kstrtos32(tempBuf, 10, &tempInt);
3451 if ( v < 0) return -EINVAL;
3452
3453 *pChannel = tempInt;
3454
3455 /* point to the next argument */
3456 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3457 /*no argument after the command*/
3458 if (NULL == inPtr) return -EINVAL;
3459 /*removing empty spaces*/
3460 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3461
3462 /*no argument followed by spaces*/
3463 if ('\0' == *inPtr)
3464 {
3465 return -EINVAL;
3466 }
3467
3468 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003469 v = sscanf(inPtr, "%32s ", tempBuf);
3470 if (1 != v) return -EINVAL;
3471
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003472 v = kstrtos32(tempBuf, 10, &tempInt);
3473 if ( v < 0) return -EINVAL;
3474
3475 *pDwellTime = tempInt;
3476
3477 /* point to the next argument */
3478 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3479 /*no argument after the command*/
3480 if (NULL == inPtr) return -EINVAL;
3481 /*removing empty spaces*/
3482 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3483
3484 /*no argument followed by spaces*/
3485 if ('\0' == *inPtr)
3486 {
3487 return -EINVAL;
3488 }
3489
3490 /* find the length of data */
3491 dataEnd = inPtr;
3492 while(('\0' != *dataEnd) )
3493 {
3494 dataEnd++;
3495 ++(*pBufLen);
3496 }
3497 if ( *pBufLen <= 0) return -EINVAL;
3498
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07003499 /* Allocate the number of bytes based on the number of input characters
3500 whether it is even or odd.
3501 if the number of input characters are even, then we need N/2 byte.
3502 if the number of input characters are odd, then we need do (N+1)/2 to
3503 compensate rounding off.
3504 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
3505 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
3506 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003507 if (NULL == *pBuf)
3508 {
3509 hddLog(VOS_TRACE_LEVEL_FATAL,
3510 "%s: vos_mem_alloc failed ", __func__);
3511 return -EINVAL;
3512 }
3513
3514 /* the buffer received from the upper layer is character buffer,
3515 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
3516 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
3517 and f0 in 3rd location */
3518 for (i = 0, j = 0; j < *pBufLen; j += 2)
3519 {
3520 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
3521 (*pBuf)[i++] = tempByte;
3522 }
3523 *pBufLen = i;
3524 return VOS_STATUS_SUCCESS;
3525}
3526
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003527/**---------------------------------------------------------------------------
3528
Srinivas Girigowdade697412013-02-14 16:31:48 -08003529 \brief hdd_parse_channellist() - HDD Parse channel list
3530
3531 This function parses the channel list passed in the format
3532 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003533 if the Number of channels (N) does not match with the actual number of channels passed
3534 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
3535 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
3536 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
3537 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08003538
3539 \param - pValue Pointer to input channel list
3540 \param - ChannelList Pointer to local output array to record channel list
3541 \param - pNumChannels Pointer to number of roam scan channels
3542
3543 \return - 0 for success non-zero for failure
3544
3545 --------------------------------------------------------------------------*/
3546VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
3547{
3548 tANI_U8 *inPtr = pValue;
3549 int tempInt;
3550 int j = 0;
3551 int v = 0;
3552 char buf[32];
3553
3554 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3555 /*no argument after the command*/
3556 if (NULL == inPtr)
3557 {
3558 return -EINVAL;
3559 }
3560
3561 /*no space after the command*/
3562 else if (SPACE_ASCII_VALUE != *inPtr)
3563 {
3564 return -EINVAL;
3565 }
3566
3567 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003568 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003569
3570 /*no argument followed by spaces*/
3571 if ('\0' == *inPtr)
3572 {
3573 return -EINVAL;
3574 }
3575
3576 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003577 v = sscanf(inPtr, "%32s ", buf);
3578 if (1 != v) return -EINVAL;
3579
Srinivas Girigowdade697412013-02-14 16:31:48 -08003580 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003581 if ((v < 0) ||
3582 (tempInt <= 0) ||
3583 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
3584 {
3585 return -EINVAL;
3586 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003587
3588 *pNumChannels = tempInt;
3589
3590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3591 "Number of channels are: %d", *pNumChannels);
3592
3593 for (j = 0; j < (*pNumChannels); j++)
3594 {
3595 /*inPtr pointing to the beginning of first space after number of channels*/
3596 inPtr = strpbrk( inPtr, " " );
3597 /*no channel list after the number of channels argument*/
3598 if (NULL == inPtr)
3599 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003600 if (0 != j)
3601 {
3602 *pNumChannels = j;
3603 return VOS_STATUS_SUCCESS;
3604 }
3605 else
3606 {
3607 return -EINVAL;
3608 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003609 }
3610
3611 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003612 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003613
3614 /*no channel list after the number of channels argument and spaces*/
3615 if ( '\0' == *inPtr )
3616 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003617 if (0 != j)
3618 {
3619 *pNumChannels = j;
3620 return VOS_STATUS_SUCCESS;
3621 }
3622 else
3623 {
3624 return -EINVAL;
3625 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003626 }
3627
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003628 v = sscanf(inPtr, "%32s ", buf);
3629 if (1 != v) return -EINVAL;
3630
Srinivas Girigowdade697412013-02-14 16:31:48 -08003631 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003632 if ((v < 0) ||
3633 (tempInt <= 0) ||
3634 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3635 {
3636 return -EINVAL;
3637 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003638 pChannelList[j] = tempInt;
3639
3640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3641 "Channel %d added to preferred channel list",
3642 pChannelList[j] );
3643 }
3644
Srinivas Girigowdade697412013-02-14 16:31:48 -08003645 return VOS_STATUS_SUCCESS;
3646}
3647
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003648
3649/**---------------------------------------------------------------------------
3650
3651 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
3652
3653 This function parses the reasoc command data passed in the format
3654 REASSOC<space><bssid><space><channel>
3655
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003656 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003657 \param - pTargetApBssid Pointer to target Ap bssid
3658 \param - pChannel Pointer to the Target AP channel
3659
3660 \return - 0 for success non-zero for failure
3661
3662 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003663VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
3664 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003665{
3666 tANI_U8 *inPtr = pValue;
3667 int tempInt;
3668 int v = 0;
3669 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003670 /* 12 hexa decimal digits and 5 ':' */
3671 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003672
3673 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3674 /*no argument after the command*/
3675 if (NULL == inPtr)
3676 {
3677 return -EINVAL;
3678 }
3679
3680 /*no space after the command*/
3681 else if (SPACE_ASCII_VALUE != *inPtr)
3682 {
3683 return -EINVAL;
3684 }
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
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003695 v = sscanf(inPtr, "%17s", macAddress);
3696 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003697 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003698 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3699 "Invalid MAC address or All hex inputs are not read (%d)", v);
3700 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003701 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003702
3703 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3704 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3705 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3706 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3707 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3708 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003709
3710 /* point to the next argument */
3711 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3712 /*no argument after the command*/
3713 if (NULL == inPtr) return -EINVAL;
3714
3715 /*removing empty spaces*/
3716 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3717
3718 /*no argument followed by spaces*/
3719 if ('\0' == *inPtr)
3720 {
3721 return -EINVAL;
3722 }
3723
3724 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003725 v = sscanf(inPtr, "%32s ", tempBuf);
3726 if (1 != v) return -EINVAL;
3727
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003728 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003729 if ((v < 0) ||
3730 (tempInt <= 0) ||
3731 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3732 {
3733 return -EINVAL;
3734 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003735
3736 *pChannel = tempInt;
3737 return VOS_STATUS_SUCCESS;
3738}
3739
3740#endif
3741
Jeff Johnson295189b2012-06-20 16:38:30 -07003742/**---------------------------------------------------------------------------
3743
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003744 \brief hdd_is_valid_mac_address() - Validate MAC address
3745
3746 This function validates whether the given MAC address is valid or not
3747 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
3748 where X is the hexa decimal digit character and separated by ':'
3749 This algorithm works even if MAC address is not separated by ':'
3750
3751 This code checks given input string mac contains exactly 12 hexadecimal digits.
3752 and a separator colon : appears in the input string only after
3753 an even number of hex digits.
3754
3755 \param - pMacAddr pointer to the input MAC address
3756 \return - 1 for valid and 0 for invalid
3757
3758 --------------------------------------------------------------------------*/
3759
3760v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
3761{
3762 int xdigit = 0;
3763 int separator = 0;
3764 while (*pMacAddr)
3765 {
3766 if (isxdigit(*pMacAddr))
3767 {
3768 xdigit++;
3769 }
3770 else if (':' == *pMacAddr)
3771 {
3772 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
3773 break;
3774
3775 ++separator;
3776 }
3777 else
3778 {
3779 separator = -1;
3780 /* Invalid MAC found */
3781 return 0;
3782 }
3783 ++pMacAddr;
3784 }
3785 return (xdigit == 12 && (separator == 5 || separator == 0));
3786}
3787
3788/**---------------------------------------------------------------------------
3789
Jeff Johnson295189b2012-06-20 16:38:30 -07003790 \brief hdd_open() - HDD Open function
3791
3792 This is called in response to ifconfig up
3793
3794 \param - dev Pointer to net_device structure
3795
3796 \return - 0 for success non-zero for failure
3797
3798 --------------------------------------------------------------------------*/
3799int hdd_open (struct net_device *dev)
3800{
3801 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3802 hdd_context_t *pHddCtx;
3803 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3804 VOS_STATUS status;
3805 v_BOOL_t in_standby = TRUE;
3806
3807 if (NULL == pAdapter)
3808 {
3809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003810 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003811 return -ENODEV;
3812 }
3813
3814 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3815 if (NULL == pHddCtx)
3816 {
3817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003818 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003819 return -ENODEV;
3820 }
3821
3822 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3823 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
3824 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003825 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
3826 {
3827 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05303828 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003829 in_standby = FALSE;
3830 break;
3831 }
3832 else
3833 {
3834 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3835 pAdapterNode = pNext;
3836 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003837 }
3838
3839 if (TRUE == in_standby)
3840 {
3841 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
3842 {
3843 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
3844 "wlan out of power save", __func__);
3845 return -EINVAL;
3846 }
3847 }
3848
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003849 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07003850 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
3851 {
3852 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003853 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003854 /* Enable TX queues only when we are connected */
3855 netif_tx_start_all_queues(dev);
3856 }
3857
3858 return 0;
3859}
3860
3861int hdd_mon_open (struct net_device *dev)
3862{
3863 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3864
3865 if(pAdapter == NULL) {
3866 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003867 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08003868 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07003869 }
3870
3871 netif_start_queue(dev);
3872
3873 return 0;
3874}
3875/**---------------------------------------------------------------------------
3876
3877 \brief hdd_stop() - HDD stop function
3878
3879 This is called in response to ifconfig down
3880
3881 \param - dev Pointer to net_device structure
3882
3883 \return - 0 for success non-zero for failure
3884
3885 --------------------------------------------------------------------------*/
3886
3887int hdd_stop (struct net_device *dev)
3888{
3889 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3890 hdd_context_t *pHddCtx;
3891 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
3892 VOS_STATUS status;
3893 v_BOOL_t enter_standby = TRUE;
3894
3895 ENTER();
3896
3897 if (NULL == pAdapter)
3898 {
3899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003900 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003901 return -ENODEV;
3902 }
3903
3904 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
3905 if (NULL == pHddCtx)
3906 {
3907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07003908 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07003909 return -ENODEV;
3910 }
3911
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003912 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07003913 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
3914 netif_tx_disable(pAdapter->dev);
3915 netif_carrier_off(pAdapter->dev);
3916
3917
3918 /* SoftAP ifaces should never go in power save mode
3919 making sure same here. */
3920 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
3921 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07003922 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07003923 )
3924 {
3925 /* SoftAP mode, so return from here */
3926 EXIT();
3927 return 0;
3928 }
3929
3930 /* Find if any iface is up then
3931 if any iface is up then can't put device to sleep/ power save mode. */
3932 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
3933 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
3934 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003935 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
3936 {
3937 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05303938 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07003939 enter_standby = FALSE;
3940 break;
3941 }
3942 else
3943 {
3944 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
3945 pAdapterNode = pNext;
3946 }
Jeff Johnson295189b2012-06-20 16:38:30 -07003947 }
3948
3949 if (TRUE == enter_standby)
3950 {
3951 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
3952 "entering standby", __func__);
3953 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
3954 {
3955 /*log and return success*/
3956 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
3957 "wlan in power save", __func__);
3958 }
3959 }
3960
3961 EXIT();
3962 return 0;
3963}
3964
3965/**---------------------------------------------------------------------------
3966
3967 \brief hdd_uninit() - HDD uninit function
3968
3969 This is called during the netdev unregister to uninitialize all data
3970associated with the device
3971
3972 \param - dev Pointer to net_device structure
3973
3974 \return - void
3975
3976 --------------------------------------------------------------------------*/
3977static void hdd_uninit (struct net_device *dev)
3978{
3979 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
3980
3981 ENTER();
3982
3983 do
3984 {
3985 if (NULL == pAdapter)
3986 {
3987 hddLog(VOS_TRACE_LEVEL_FATAL,
3988 "%s: NULL pAdapter", __func__);
3989 break;
3990 }
3991
3992 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
3993 {
3994 hddLog(VOS_TRACE_LEVEL_FATAL,
3995 "%s: Invalid magic", __func__);
3996 break;
3997 }
3998
3999 if (NULL == pAdapter->pHddCtx)
4000 {
4001 hddLog(VOS_TRACE_LEVEL_FATAL,
4002 "%s: NULL pHddCtx", __func__);
4003 break;
4004 }
4005
4006 if (dev != pAdapter->dev)
4007 {
4008 hddLog(VOS_TRACE_LEVEL_FATAL,
4009 "%s: Invalid device reference", __func__);
4010 /* we haven't validated all cases so let this go for now */
4011 }
4012
4013 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4014
4015 /* after uninit our adapter structure will no longer be valid */
4016 pAdapter->dev = NULL;
4017 pAdapter->magic = 0;
4018 } while (0);
4019
4020 EXIT();
4021}
4022
4023/**---------------------------------------------------------------------------
4024
4025 \brief hdd_release_firmware() -
4026
4027 This function calls the release firmware API to free the firmware buffer.
4028
4029 \param - pFileName Pointer to the File Name.
4030 pCtx - Pointer to the adapter .
4031
4032
4033 \return - 0 for success, non zero for failure
4034
4035 --------------------------------------------------------------------------*/
4036
4037VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4038{
4039 VOS_STATUS status = VOS_STATUS_SUCCESS;
4040 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4041 ENTER();
4042
4043
4044 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4045
4046 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4047
4048 if(pHddCtx->fw) {
4049 release_firmware(pHddCtx->fw);
4050 pHddCtx->fw = NULL;
4051 }
4052 else
4053 status = VOS_STATUS_E_FAILURE;
4054 }
4055 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4056 if(pHddCtx->nv) {
4057 release_firmware(pHddCtx->nv);
4058 pHddCtx->nv = NULL;
4059 }
4060 else
4061 status = VOS_STATUS_E_FAILURE;
4062
4063 }
4064
4065 EXIT();
4066 return status;
4067}
4068
4069/**---------------------------------------------------------------------------
4070
4071 \brief hdd_request_firmware() -
4072
4073 This function reads the firmware file using the request firmware
4074 API and returns the the firmware data and the firmware file size.
4075
4076 \param - pfileName - Pointer to the file name.
4077 - pCtx - Pointer to the adapter .
4078 - ppfw_data - Pointer to the pointer of the firmware data.
4079 - pSize - Pointer to the file size.
4080
4081 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4082
4083 --------------------------------------------------------------------------*/
4084
4085
4086VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4087{
4088 int status;
4089 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4090 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4091 ENTER();
4092
4093 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4094
4095 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4096
4097 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4098 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4099 __func__, pfileName);
4100 retval = VOS_STATUS_E_FAILURE;
4101 }
4102
4103 else {
4104 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4105 *pSize = pHddCtx->fw->size;
4106 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4107 __func__, *pSize);
4108 }
4109 }
4110 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4111
4112 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4113
4114 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4115 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4116 __func__, pfileName);
4117 retval = VOS_STATUS_E_FAILURE;
4118 }
4119
4120 else {
4121 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4122 *pSize = pHddCtx->nv->size;
4123 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4124 __func__, *pSize);
4125 }
4126 }
4127
4128 EXIT();
4129 return retval;
4130}
4131/**---------------------------------------------------------------------------
4132 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4133
4134 This is the function invoked by SME to inform the result of a full power
4135 request issued by HDD
4136
4137 \param - callbackcontext - Pointer to cookie
4138 status - result of request
4139
4140 \return - None
4141
4142--------------------------------------------------------------------------*/
4143void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4144{
4145 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4146
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004147 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004148 if(&pHddCtx->full_pwr_comp_var)
4149 {
4150 complete(&pHddCtx->full_pwr_comp_var);
4151 }
4152}
4153
4154/**---------------------------------------------------------------------------
4155
4156 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4157
4158 This is the function invoked by SME to inform the result of BMPS
4159 request issued by HDD
4160
4161 \param - callbackcontext - Pointer to cookie
4162 status - result of request
4163
4164 \return - None
4165
4166--------------------------------------------------------------------------*/
4167void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4168{
4169
4170 struct completion *completion_var = (struct completion*) callbackContext;
4171
4172 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4173 if(completion_var != NULL)
4174 {
4175 complete(completion_var);
4176 }
4177}
4178
4179/**---------------------------------------------------------------------------
4180
4181 \brief hdd_get_cfg_file_size() -
4182
4183 This function reads the configuration file using the request firmware
4184 API and returns the configuration file size.
4185
4186 \param - pCtx - Pointer to the adapter .
4187 - pFileName - Pointer to the file name.
4188 - pBufSize - Pointer to the buffer size.
4189
4190 \return - 0 for success, non zero for failure
4191
4192 --------------------------------------------------------------------------*/
4193
4194VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4195{
4196 int status;
4197 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4198
4199 ENTER();
4200
4201 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4202
4203 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4204 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4205 status = VOS_STATUS_E_FAILURE;
4206 }
4207 else {
4208 *pBufSize = pHddCtx->fw->size;
4209 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4210 release_firmware(pHddCtx->fw);
4211 pHddCtx->fw = NULL;
4212 }
4213
4214 EXIT();
4215 return VOS_STATUS_SUCCESS;
4216}
4217
4218/**---------------------------------------------------------------------------
4219
4220 \brief hdd_read_cfg_file() -
4221
4222 This function reads the configuration file using the request firmware
4223 API and returns the cfg data and the buffer size of the configuration file.
4224
4225 \param - pCtx - Pointer to the adapter .
4226 - pFileName - Pointer to the file name.
4227 - pBuffer - Pointer to the data buffer.
4228 - pBufSize - Pointer to the buffer size.
4229
4230 \return - 0 for success, non zero for failure
4231
4232 --------------------------------------------------------------------------*/
4233
4234VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4235 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4236{
4237 int status;
4238 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4239
4240 ENTER();
4241
4242 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4243
4244 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4245 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4246 return VOS_STATUS_E_FAILURE;
4247 }
4248 else {
4249 if(*pBufSize != pHddCtx->fw->size) {
4250 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4251 "file size", __func__);
4252 release_firmware(pHddCtx->fw);
4253 pHddCtx->fw = NULL;
4254 return VOS_STATUS_E_FAILURE;
4255 }
4256 else {
4257 if(pBuffer) {
4258 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4259 }
4260 release_firmware(pHddCtx->fw);
4261 pHddCtx->fw = NULL;
4262 }
4263 }
4264
4265 EXIT();
4266
4267 return VOS_STATUS_SUCCESS;
4268}
4269
4270/**---------------------------------------------------------------------------
4271
Jeff Johnson295189b2012-06-20 16:38:30 -07004272 \brief hdd_set_mac_address() -
4273
4274 This function sets the user specified mac address using
4275 the command ifconfig wlanX hw ether <mac adress>.
4276
4277 \param - dev - Pointer to the net device.
4278 - addr - Pointer to the sockaddr.
4279 \return - 0 for success, non zero for failure
4280
4281 --------------------------------------------------------------------------*/
4282
4283static int hdd_set_mac_address(struct net_device *dev, void *addr)
4284{
4285 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4286 struct sockaddr *psta_mac_addr = addr;
4287 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4288
4289 ENTER();
4290
4291 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4292
4293#ifdef HDD_SESSIONIZE
4294 // set the MAC address though the STA ID CFG.
4295 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4296 (v_U8_t *)&pAdapter->macAddressCurrent,
4297 sizeof( pAdapter->macAddressCurrent ),
4298 hdd_set_mac_addr_cb, VOS_FALSE );
4299#endif
4300
4301 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4302
4303 EXIT();
4304 return halStatus;
4305}
4306
4307tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4308{
4309 int i;
4310 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4311 {
4312 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4313 break;
4314 }
4315
4316 if( VOS_MAX_CONCURRENCY_PERSONA == i)
4317 return NULL;
4318
4319 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
4320 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
4321}
4322
4323void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
4324{
4325 int i;
4326 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4327 {
4328 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
4329 {
4330 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
4331 break;
4332 }
4333 }
4334 return;
4335}
4336
4337#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4338 static struct net_device_ops wlan_drv_ops = {
4339 .ndo_open = hdd_open,
4340 .ndo_stop = hdd_stop,
4341 .ndo_uninit = hdd_uninit,
4342 .ndo_start_xmit = hdd_hard_start_xmit,
4343 .ndo_tx_timeout = hdd_tx_timeout,
4344 .ndo_get_stats = hdd_stats,
4345 .ndo_do_ioctl = hdd_ioctl,
4346 .ndo_set_mac_address = hdd_set_mac_address,
4347 .ndo_select_queue = hdd_select_queue,
4348#ifdef WLAN_FEATURE_PACKET_FILTERING
4349#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
4350 .ndo_set_rx_mode = hdd_set_multicast_list,
4351#else
4352 .ndo_set_multicast_list = hdd_set_multicast_list,
4353#endif //LINUX_VERSION_CODE
4354#endif
4355 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004356 static struct net_device_ops wlan_mon_drv_ops = {
4357 .ndo_open = hdd_mon_open,
4358 .ndo_stop = hdd_stop,
4359 .ndo_uninit = hdd_uninit,
4360 .ndo_start_xmit = hdd_mon_hard_start_xmit,
4361 .ndo_tx_timeout = hdd_tx_timeout,
4362 .ndo_get_stats = hdd_stats,
4363 .ndo_do_ioctl = hdd_ioctl,
4364 .ndo_set_mac_address = hdd_set_mac_address,
4365 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004366
4367#endif
4368
4369void hdd_set_station_ops( struct net_device *pWlanDev )
4370{
4371#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4372 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
4373 pWlanDev->netdev_ops = &wlan_drv_ops;
4374#else
4375 pWlanDev->open = hdd_open;
4376 pWlanDev->stop = hdd_stop;
4377 pWlanDev->uninit = hdd_uninit;
4378 pWlanDev->hard_start_xmit = NULL;
4379 pWlanDev->tx_timeout = hdd_tx_timeout;
4380 pWlanDev->get_stats = hdd_stats;
4381 pWlanDev->do_ioctl = hdd_ioctl;
4382 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
4383 pWlanDev->set_mac_address = hdd_set_mac_address;
4384#endif
4385}
4386
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004387static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07004388{
4389 struct net_device *pWlanDev = NULL;
4390 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004391 /*
4392 * cfg80211 initialization and registration....
4393 */
4394 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
4395
Jeff Johnson295189b2012-06-20 16:38:30 -07004396 if(pWlanDev != NULL)
4397 {
4398
4399 //Save the pointer to the net_device in the HDD adapter
4400 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
4401
Jeff Johnson295189b2012-06-20 16:38:30 -07004402 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
4403
4404 pAdapter->dev = pWlanDev;
4405 pAdapter->pHddCtx = pHddCtx;
4406 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
4407
4408 init_completion(&pAdapter->session_open_comp_var);
4409 init_completion(&pAdapter->session_close_comp_var);
4410 init_completion(&pAdapter->disconnect_comp_var);
4411 init_completion(&pAdapter->linkup_event_var);
4412 init_completion(&pAdapter->cancel_rem_on_chan_var);
4413 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004414#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4415 init_completion(&pAdapter->offchannel_tx_event);
4416#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004417 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004418#ifdef FEATURE_WLAN_TDLS
4419 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07004420 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08004421 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05304422 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004423#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004424 init_completion(&pHddCtx->mc_sus_event_var);
4425 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05304426 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07004427 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07004428 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07004429
Rajeev79dbe4c2013-10-05 11:03:42 +05304430#ifdef FEATURE_WLAN_BATCH_SCAN
4431 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
4432 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
4433 pAdapter->pBatchScanRsp = NULL;
4434 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07004435 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05304436 mutex_init(&pAdapter->hdd_batch_scan_lock);
4437#endif
4438
Jeff Johnson295189b2012-06-20 16:38:30 -07004439 pAdapter->isLinkUpSvcNeeded = FALSE;
4440 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
4441 //Init the net_device structure
4442 strlcpy(pWlanDev->name, name, IFNAMSIZ);
4443
4444 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
4445 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
4446 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
4447 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
4448
4449 hdd_set_station_ops( pAdapter->dev );
4450
4451 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004452 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
4453 pAdapter->wdev.wiphy = pHddCtx->wiphy;
4454 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004455 /* set pWlanDev's parent to underlying device */
4456 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
4457 }
4458
4459 return pAdapter;
4460}
4461
4462VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
4463{
4464 struct net_device *pWlanDev = pAdapter->dev;
4465 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4466 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4467 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4468
4469 if( rtnl_lock_held )
4470 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08004471 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07004472 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
4473 {
4474 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
4475 return VOS_STATUS_E_FAILURE;
4476 }
4477 }
4478 if (register_netdevice(pWlanDev))
4479 {
4480 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
4481 return VOS_STATUS_E_FAILURE;
4482 }
4483 }
4484 else
4485 {
4486 if(register_netdev(pWlanDev))
4487 {
4488 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
4489 return VOS_STATUS_E_FAILURE;
4490 }
4491 }
4492 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
4493
4494 return VOS_STATUS_SUCCESS;
4495}
4496
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004497static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07004498{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004499 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07004500
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004501 if (NULL == pAdapter)
4502 {
4503 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
4504 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07004505 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004506
4507 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4508 {
4509 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
4510 return eHAL_STATUS_NOT_INITIALIZED;
4511 }
4512
4513 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
4514
4515 /* need to make sure all of our scheduled work has completed.
4516 * This callback is called from MC thread context, so it is safe to
4517 * to call below flush workqueue API from here.
4518 */
4519 flush_scheduled_work();
4520
4521 /* We can be blocked while waiting for scheduled work to be
4522 * flushed, and the adapter structure can potentially be freed, in
4523 * which case the magic will have been reset. So make sure the
4524 * magic is still good, and hence the adapter structure is still
4525 * valid, before signaling completion */
4526 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
4527 {
4528 complete(&pAdapter->session_close_comp_var);
4529 }
4530
Jeff Johnson295189b2012-06-20 16:38:30 -07004531 return eHAL_STATUS_SUCCESS;
4532}
4533
4534VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
4535{
4536 struct net_device *pWlanDev = pAdapter->dev;
4537 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4538 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4539 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4540 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4541 int rc = 0;
4542
4543 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004544 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07004545 //Open a SME session for future operation
4546 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004547 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4549 {
4550 hddLog(VOS_TRACE_LEVEL_FATAL,
4551 "sme_OpenSession() failed with status code %08d [x%08lx]",
4552 halStatus, halStatus );
4553 status = VOS_STATUS_E_FAILURE;
4554 goto error_sme_open;
4555 }
4556
4557 //Block on a completion variable. Can't wait forever though.
4558 rc = wait_for_completion_interruptible_timeout(
4559 &pAdapter->session_open_comp_var,
4560 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4561 if (!rc)
4562 {
4563 hddLog(VOS_TRACE_LEVEL_FATAL,
4564 "Session is not opened within timeout period code %08d", rc );
4565 status = VOS_STATUS_E_FAILURE;
4566 goto error_sme_open;
4567 }
4568
4569 // Register wireless extensions
4570 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
4571 {
4572 hddLog(VOS_TRACE_LEVEL_FATAL,
4573 "hdd_register_wext() failed with status code %08d [x%08lx]",
4574 halStatus, halStatus );
4575 status = VOS_STATUS_E_FAILURE;
4576 goto error_register_wext;
4577 }
4578 //Safe to register the hard_start_xmit function again
4579#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4580 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
4581#else
4582 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
4583#endif
4584
4585 //Set the Connection State to Not Connected
4586 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4587
4588 //Set the default operation channel
4589 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
4590
4591 /* Make the default Auth Type as OPEN*/
4592 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4593
4594 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
4595 {
4596 hddLog(VOS_TRACE_LEVEL_FATAL,
4597 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
4598 status, status );
4599 goto error_init_txrx;
4600 }
4601
4602 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4603
4604 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
4605 {
4606 hddLog(VOS_TRACE_LEVEL_FATAL,
4607 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
4608 status, status );
4609 goto error_wmm_init;
4610 }
4611
4612 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4613
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004614#ifdef FEATURE_WLAN_TDLS
4615 if(0 != wlan_hdd_tdls_init(pAdapter))
4616 {
4617 status = VOS_STATUS_E_FAILURE;
4618 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
4619 goto error_tdls_init;
4620 }
4621 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
4622#endif
4623
Jeff Johnson295189b2012-06-20 16:38:30 -07004624 return VOS_STATUS_SUCCESS;
4625
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004626#ifdef FEATURE_WLAN_TDLS
4627error_tdls_init:
4628 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4629 hdd_wmm_adapter_close(pAdapter);
4630#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004631error_wmm_init:
4632 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4633 hdd_deinit_tx_rx(pAdapter);
4634error_init_txrx:
4635 hdd_UnregisterWext(pWlanDev);
4636error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004637 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07004638 {
4639 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004640 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07004641 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004642 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07004643 {
4644 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004645 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07004646 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004647 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07004648 }
4649}
4650error_sme_open:
4651 return status;
4652}
4653
Jeff Johnson295189b2012-06-20 16:38:30 -07004654void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4655{
4656 hdd_cfg80211_state_t *cfgState;
4657
4658 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
4659
4660 if( NULL != cfgState->buf )
4661 {
4662 int rc;
4663 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
4664 rc = wait_for_completion_interruptible_timeout(
4665 &pAdapter->tx_action_cnf_event,
4666 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
4667 if(!rc)
4668 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08004669 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07004670 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
4671 }
4672 }
4673 return;
4674}
Jeff Johnson295189b2012-06-20 16:38:30 -07004675
4676void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
4677{
4678 ENTER();
4679 switch ( pAdapter->device_mode )
4680 {
4681 case WLAN_HDD_INFRA_STATION:
4682 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07004683 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07004684 {
4685 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
4686 {
4687 hdd_deinit_tx_rx( pAdapter );
4688 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4689 }
4690
4691 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
4692 {
4693 hdd_wmm_adapter_close( pAdapter );
4694 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4695 }
4696
Jeff Johnson295189b2012-06-20 16:38:30 -07004697 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004698#ifdef FEATURE_WLAN_TDLS
4699 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
4700 {
4701 wlan_hdd_tdls_exit(pAdapter);
4702 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
4703 }
4704#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004705
4706 break;
4707 }
4708
4709 case WLAN_HDD_SOFTAP:
4710 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004711 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05304712
4713 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
4714 {
4715 hdd_wmm_adapter_close( pAdapter );
4716 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4717 }
4718
Jeff Johnson295189b2012-06-20 16:38:30 -07004719 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07004720
4721 hdd_unregister_hostapd(pAdapter);
4722 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07004723 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07004724 break;
4725 }
4726
4727 case WLAN_HDD_MONITOR:
4728 {
Jeff Johnson295189b2012-06-20 16:38:30 -07004729 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07004730 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
4731 {
4732 hdd_deinit_tx_rx( pAdapter );
4733 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4734 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004735 if(NULL != pAdapterforTx)
4736 {
4737 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
4738 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004739 break;
4740 }
4741
4742
4743 default:
4744 break;
4745 }
4746
4747 EXIT();
4748}
4749
4750void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
4751{
4752 struct net_device *pWlanDev = pAdapter->dev;
4753
Rajeev79dbe4c2013-10-05 11:03:42 +05304754#ifdef FEATURE_WLAN_BATCH_SCAN
4755 tHddBatchScanRsp *pNode;
4756 tHddBatchScanRsp *pPrev;
4757 if (pAdapter)
4758 {
4759 mutex_lock(&pAdapter->hdd_batch_scan_lock);
4760 pNode = pAdapter->pBatchScanRsp;
4761 while (pNode)
4762 {
4763 pPrev = pNode;
4764 pNode = pNode->pNext;
4765 vos_mem_free((v_VOID_t * )pPrev);
4766 }
4767 pAdapter->pBatchScanRsp = NULL;
4768 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
4769 }
4770#endif
4771
Jeff Johnson295189b2012-06-20 16:38:30 -07004772 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
4773 if( rtnl_held )
4774 {
4775 unregister_netdevice(pWlanDev);
4776 }
4777 else
4778 {
4779 unregister_netdev(pWlanDev);
4780 }
4781 // note that the pAdapter is no longer valid at this point
4782 // since the memory has been reclaimed
4783 }
4784
4785}
4786
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004787void hdd_set_pwrparams(hdd_context_t *pHddCtx)
4788{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304789 VOS_STATUS status;
4790 hdd_adapter_t *pAdapter = NULL;
4791 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004792
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304793 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004794
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304795 /*loop through all adapters.*/
4796 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004797 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304798 pAdapter = pAdapterNode->pAdapter;
4799 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
4800 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004801
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304802 { // we skip this registration for modes other than STA and P2P client modes.
4803 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4804 pAdapterNode = pNext;
4805 continue;
4806 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004807
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304808 //Apply Dynamic DTIM For P2P
4809 //Only if ignoreDynamicDtimInP2pMode is not set in ini
4810 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
4811 pHddCtx->cfg_ini->enableModulatedDTIM) &&
4812 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
4813 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
4814 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
4815 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
4816 (eConnectionState_Associated ==
4817 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
4818 (pHddCtx->cfg_ini->fIsBmpsEnabled))
4819 {
4820 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004821
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05304822 powerRequest.uIgnoreDTIM = 1;
4823 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
4824
4825 if (pHddCtx->cfg_ini->enableModulatedDTIM)
4826 {
4827 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
4828 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
4829 }
4830 else
4831 {
4832 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
4833 }
4834
4835 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
4836 * specified during Enter/Exit BMPS when LCD off*/
4837 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
4838 NULL, eANI_BOOLEAN_FALSE);
4839 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
4840 NULL, eANI_BOOLEAN_FALSE);
4841
4842 /* switch to the DTIM specified in cfg.ini */
4843 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4844 "Switch to DTIM %d", powerRequest.uListenInterval);
4845 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
4846 break;
4847
4848 }
4849
4850 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4851 pAdapterNode = pNext;
4852 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004853}
4854
4855void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
4856{
4857 /*Switch back to DTIM 1*/
4858 tSirSetPowerParamsReq powerRequest = { 0 };
4859
4860 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
4861 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07004862 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08004863
4864 /* Update ignoreDTIM and ListedInterval in CFG with default values */
4865 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
4866 NULL, eANI_BOOLEAN_FALSE);
4867 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
4868 NULL, eANI_BOOLEAN_FALSE);
4869
4870 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4871 "Switch to DTIM%d",powerRequest.uListenInterval);
4872 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
4873
4874}
4875
Jeff Johnson295189b2012-06-20 16:38:30 -07004876VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
4877{
4878 VOS_STATUS status = VOS_STATUS_SUCCESS;
4879
4880 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
4881 {
4882 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4883 }
4884
4885 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
4886 {
4887 sme_StartAutoBmpsTimer(pHddCtx->hHal);
4888 }
4889
4890 if (pHddCtx->cfg_ini->fIsImpsEnabled)
4891 {
4892 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4893 }
4894
4895 return status;
4896}
4897
4898VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
4899{
4900 hdd_adapter_t *pAdapter = NULL;
4901 eHalStatus halStatus;
4902 VOS_STATUS status = VOS_STATUS_E_INVAL;
4903 v_BOOL_t disableBmps = FALSE;
4904 v_BOOL_t disableImps = FALSE;
4905
4906 switch(session_type)
4907 {
4908 case WLAN_HDD_INFRA_STATION:
4909 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07004910 case WLAN_HDD_P2P_CLIENT:
4911 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07004912 //Exit BMPS -> Is Sta/P2P Client is already connected
4913 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
4914 if((NULL != pAdapter)&&
4915 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4916 {
4917 disableBmps = TRUE;
4918 }
4919
4920 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
4921 if((NULL != pAdapter)&&
4922 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4923 {
4924 disableBmps = TRUE;
4925 }
4926
4927 //Exit both Bmps and Imps incase of Go/SAP Mode
4928 if((WLAN_HDD_SOFTAP == session_type) ||
4929 (WLAN_HDD_P2P_GO == session_type))
4930 {
4931 disableBmps = TRUE;
4932 disableImps = TRUE;
4933 }
4934
4935 if(TRUE == disableImps)
4936 {
4937 if (pHddCtx->cfg_ini->fIsImpsEnabled)
4938 {
4939 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
4940 }
4941 }
4942
4943 if(TRUE == disableBmps)
4944 {
4945 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
4946 {
4947 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
4948
4949 if(eHAL_STATUS_SUCCESS != halStatus)
4950 {
4951 status = VOS_STATUS_E_FAILURE;
4952 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
4953 VOS_ASSERT(0);
4954 return status;
4955 }
4956 }
4957
4958 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
4959 {
4960 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
4961
4962 if(eHAL_STATUS_SUCCESS != halStatus)
4963 {
4964 status = VOS_STATUS_E_FAILURE;
4965 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
4966 VOS_ASSERT(0);
4967 return status;
4968 }
4969 }
4970 }
4971
4972 if((TRUE == disableBmps) ||
4973 (TRUE == disableImps))
4974 {
4975 /* Now, get the chip into Full Power now */
4976 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
4977 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
4978 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
4979
4980 if(halStatus != eHAL_STATUS_SUCCESS)
4981 {
4982 if(halStatus == eHAL_STATUS_PMC_PENDING)
4983 {
4984 //Block on a completion variable. Can't wait forever though
4985 wait_for_completion_interruptible_timeout(
4986 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
4987 }
4988 else
4989 {
4990 status = VOS_STATUS_E_FAILURE;
4991 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
4992 VOS_ASSERT(0);
4993 return status;
4994 }
4995 }
4996
4997 status = VOS_STATUS_SUCCESS;
4998 }
4999
5000 break;
5001 }
5002 return status;
5003}
5004
5005hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005006 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005007 tANI_U8 rtnl_held )
5008{
5009 hdd_adapter_t *pAdapter = NULL;
5010 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5011 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5012 VOS_STATUS exitbmpsStatus;
5013
5014 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5015
5016 //Disable BMPS incase of Concurrency
5017 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5018
5019 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5020 {
5021 //Fail to Exit BMPS
5022 VOS_ASSERT(0);
5023 return NULL;
5024 }
5025
5026 switch(session_type)
5027 {
5028 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005029 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005030 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005031 {
5032 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5033
5034 if( NULL == pAdapter )
5035 return NULL;
5036
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305037#ifdef FEATURE_WLAN_TDLS
5038 /* A Mutex Lock is introduced while changing/initializing the mode to
5039 * protect the concurrent access for the Adapters by TDLS module.
5040 */
5041 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5042 {
5043 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5044 "%s: unable to lock list", __func__);
5045 return NULL;
5046 }
5047#endif
5048
Jeff Johnsone7245742012-09-05 17:12:55 -07005049 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5050 NL80211_IFTYPE_P2P_CLIENT:
5051 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005052
Jeff Johnson295189b2012-06-20 16:38:30 -07005053 pAdapter->device_mode = session_type;
5054
5055 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305056#ifdef FEATURE_WLAN_TDLS
5057 mutex_unlock(&pHddCtx->tdls_lock);
5058#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005059 if( VOS_STATUS_SUCCESS != status )
5060 goto err_free_netdev;
5061
5062 status = hdd_register_interface( pAdapter, rtnl_held );
5063 if( VOS_STATUS_SUCCESS != status )
5064 {
5065 hdd_deinit_adapter(pHddCtx, pAdapter);
5066 goto err_free_netdev;
5067 }
5068 //Stop the Interface TX queue.
5069 netif_tx_disable(pAdapter->dev);
5070 //netif_tx_disable(pWlanDev);
5071 netif_carrier_off(pAdapter->dev);
5072
5073 break;
5074 }
5075
Jeff Johnson295189b2012-06-20 16:38:30 -07005076 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005077 case WLAN_HDD_SOFTAP:
5078 {
5079 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5080 if( NULL == pAdapter )
5081 return NULL;
5082
Jeff Johnson295189b2012-06-20 16:38:30 -07005083 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5084 NL80211_IFTYPE_AP:
5085 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005086 pAdapter->device_mode = session_type;
5087
5088 status = hdd_init_ap_mode(pAdapter);
5089 if( VOS_STATUS_SUCCESS != status )
5090 goto err_free_netdev;
5091
5092 status = hdd_register_hostapd( pAdapter, rtnl_held );
5093 if( VOS_STATUS_SUCCESS != status )
5094 {
5095 hdd_deinit_adapter(pHddCtx, pAdapter);
5096 goto err_free_netdev;
5097 }
5098
5099 netif_tx_disable(pAdapter->dev);
5100 netif_carrier_off(pAdapter->dev);
5101
5102 hdd_set_conparam( 1 );
5103 break;
5104 }
5105 case WLAN_HDD_MONITOR:
5106 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005107 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5108 if( NULL == pAdapter )
5109 return NULL;
5110
5111 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5112 pAdapter->device_mode = session_type;
5113 status = hdd_register_interface( pAdapter, rtnl_held );
5114#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5115 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5116#else
5117 pAdapter->dev->open = hdd_mon_open;
5118 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5119#endif
5120 hdd_init_tx_rx( pAdapter );
5121 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5122 //Set adapter to be used for data tx. It will use either GO or softap.
5123 pAdapter->sessionCtx.monitor.pAdapterForTx =
5124 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005125 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5126 {
5127 pAdapter->sessionCtx.monitor.pAdapterForTx =
5128 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5129 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005130 /* This workqueue will be used to transmit management packet over
5131 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005132 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5133 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5134 return NULL;
5135 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005136
Jeff Johnson295189b2012-06-20 16:38:30 -07005137 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5138 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005139 }
5140 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005141 case WLAN_HDD_FTM:
5142 {
5143 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5144
5145 if( NULL == pAdapter )
5146 return NULL;
5147 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5148 * message while loading driver in FTM mode. */
5149 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5150 pAdapter->device_mode = session_type;
5151 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305152
5153 hdd_init_tx_rx( pAdapter );
5154
5155 //Stop the Interface TX queue.
5156 netif_tx_disable(pAdapter->dev);
5157 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005158 }
5159 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005160 default:
5161 {
5162 VOS_ASSERT(0);
5163 return NULL;
5164 }
5165 }
5166
5167
5168 if( VOS_STATUS_SUCCESS == status )
5169 {
5170 //Add it to the hdd's session list.
5171 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5172 if( NULL == pHddAdapterNode )
5173 {
5174 status = VOS_STATUS_E_NOMEM;
5175 }
5176 else
5177 {
5178 pHddAdapterNode->pAdapter = pAdapter;
5179 status = hdd_add_adapter_back ( pHddCtx,
5180 pHddAdapterNode );
5181 }
5182 }
5183
5184 if( VOS_STATUS_SUCCESS != status )
5185 {
5186 if( NULL != pAdapter )
5187 {
5188 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5189 pAdapter = NULL;
5190 }
5191 if( NULL != pHddAdapterNode )
5192 {
5193 vos_mem_free( pHddAdapterNode );
5194 }
5195
5196 goto resume_bmps;
5197 }
5198
5199 if(VOS_STATUS_SUCCESS == status)
5200 {
5201 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5202
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005203 //Initialize the WoWL service
5204 if(!hdd_init_wowl(pAdapter))
5205 {
5206 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5207 goto err_free_netdev;
5208 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005210 return pAdapter;
5211
5212err_free_netdev:
5213 free_netdev(pAdapter->dev);
5214 wlan_hdd_release_intf_addr( pHddCtx,
5215 pAdapter->macAddressCurrent.bytes );
5216
5217resume_bmps:
5218 //If bmps disabled enable it
5219 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5220 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305221 if (pHddCtx->hdd_wlan_suspended)
5222 {
5223 hdd_set_pwrparams(pHddCtx);
5224 }
5225 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005226 }
5227 return NULL;
5228}
5229
5230VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5231 tANI_U8 rtnl_held )
5232{
5233 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5234 VOS_STATUS status;
5235
5236 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5237 if( VOS_STATUS_SUCCESS != status )
5238 return status;
5239
5240 while ( pCurrent->pAdapter != pAdapter )
5241 {
5242 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5243 if( VOS_STATUS_SUCCESS != status )
5244 break;
5245
5246 pCurrent = pNext;
5247 }
5248 pAdapterNode = pCurrent;
5249 if( VOS_STATUS_SUCCESS == status )
5250 {
5251 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5252 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305253
5254#ifdef FEATURE_WLAN_TDLS
5255
5256 /* A Mutex Lock is introduced while changing/initializing the mode to
5257 * protect the concurrent access for the Adapters by TDLS module.
5258 */
5259 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5260 {
5261 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5262 "%s: unable to lock list", __func__);
5263 return VOS_STATUS_E_FAILURE;
5264 }
5265#endif
5266
Jeff Johnson295189b2012-06-20 16:38:30 -07005267 hdd_remove_adapter( pHddCtx, pAdapterNode );
5268 vos_mem_free( pAdapterNode );
5269
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305270#ifdef FEATURE_WLAN_TDLS
5271 mutex_unlock(&pHddCtx->tdls_lock);
5272#endif
5273
Jeff Johnson295189b2012-06-20 16:38:30 -07005274
5275 /* If there is a single session of STA/P2P client, re-enable BMPS */
5276 if ((!vos_concurrent_sessions_running()) &&
5277 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5278 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5279 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305280 if (pHddCtx->hdd_wlan_suspended)
5281 {
5282 hdd_set_pwrparams(pHddCtx);
5283 }
5284 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005285 }
5286
5287 return VOS_STATUS_SUCCESS;
5288 }
5289
5290 return VOS_STATUS_E_FAILURE;
5291}
5292
5293VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5294{
5295 hdd_adapter_list_node_t *pHddAdapterNode;
5296 VOS_STATUS status;
5297
5298 ENTER();
5299
5300 do
5301 {
5302 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5303 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5304 {
5305 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
5306 vos_mem_free( pHddAdapterNode );
5307 }
5308 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
5309
5310 EXIT();
5311
5312 return VOS_STATUS_SUCCESS;
5313}
5314
5315void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
5316{
5317 v_U8_t addIE[1] = {0};
5318
5319 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5320 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
5321 eANI_BOOLEAN_FALSE) )
5322 {
5323 hddLog(LOGE,
5324 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
5325 }
5326
5327 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5328 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
5329 eANI_BOOLEAN_FALSE) )
5330 {
5331 hddLog(LOGE,
5332 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
5333 }
5334
5335 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5336 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
5337 eANI_BOOLEAN_FALSE) )
5338 {
5339 hddLog(LOGE,
5340 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
5341 }
5342}
5343
5344VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5345{
5346 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5347 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5348 union iwreq_data wrqu;
5349
5350 ENTER();
5351
5352 switch(pAdapter->device_mode)
5353 {
5354 case WLAN_HDD_INFRA_STATION:
5355 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005356 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005357 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5358 {
5359 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
5360 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5361 pAdapter->sessionId,
5362 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5363 else
5364 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5365 pAdapter->sessionId,
5366 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5367 //success implies disconnect command got queued up successfully
5368 if(halStatus == eHAL_STATUS_SUCCESS)
5369 {
5370 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
5371 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5372 }
5373 memset(&wrqu, '\0', sizeof(wrqu));
5374 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5375 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5376 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
5377 }
5378 else
5379 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305380 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 }
5382
5383 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
5384 {
5385 INIT_COMPLETION(pAdapter->session_close_comp_var);
5386 if (eHAL_STATUS_SUCCESS ==
5387 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
5388 hdd_smeCloseSessionCallback, pAdapter))
5389 {
5390 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005391 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005392 &pAdapter->session_close_comp_var,
5393 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5394 }
5395 }
5396
5397 break;
5398
5399 case WLAN_HDD_SOFTAP:
5400 case WLAN_HDD_P2P_GO:
5401 //Any softap specific cleanup here...
5402 mutex_lock(&pHddCtx->sap_lock);
5403 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5404 {
5405 VOS_STATUS status;
5406 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5407
5408 //Stop Bss.
5409 status = WLANSAP_StopBss(pHddCtx->pvosContext);
5410 if (VOS_IS_STATUS_SUCCESS(status))
5411 {
5412 hdd_hostapd_state_t *pHostapdState =
5413 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5414
5415 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
5416
5417 if (!VOS_IS_STATUS_SUCCESS(status))
5418 {
5419 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005420 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005421 }
5422 }
5423 else
5424 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005425 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005426 }
5427 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
5428
5429 if (eHAL_STATUS_FAILURE ==
5430 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5431 0, NULL, eANI_BOOLEAN_FALSE))
5432 {
5433 hddLog(LOGE,
5434 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005435 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005436 }
5437
5438 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
5439 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5440 eANI_BOOLEAN_FALSE) )
5441 {
5442 hddLog(LOGE,
5443 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
5444 }
5445
5446 // Reset WNI_CFG_PROBE_RSP Flags
5447 wlan_hdd_reset_prob_rspies(pAdapter);
5448 kfree(pAdapter->sessionCtx.ap.beacon);
5449 pAdapter->sessionCtx.ap.beacon = NULL;
5450 }
5451 mutex_unlock(&pHddCtx->sap_lock);
5452 break;
5453 case WLAN_HDD_MONITOR:
5454 break;
5455 default:
5456 break;
5457 }
5458
5459 EXIT();
5460 return VOS_STATUS_SUCCESS;
5461}
5462
5463VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
5464{
5465 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5466 VOS_STATUS status;
5467 hdd_adapter_t *pAdapter;
5468
5469 ENTER();
5470
5471 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5472
5473 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5474 {
5475 pAdapter = pAdapterNode->pAdapter;
5476 netif_tx_disable(pAdapter->dev);
5477 netif_carrier_off(pAdapter->dev);
5478
5479 hdd_stop_adapter( pHddCtx, pAdapter );
5480
5481 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5482 pAdapterNode = pNext;
5483 }
5484
5485 EXIT();
5486
5487 return VOS_STATUS_SUCCESS;
5488}
5489
5490VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
5491{
5492 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5493 VOS_STATUS status;
5494 hdd_adapter_t *pAdapter;
5495
5496 ENTER();
5497
5498 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5499
5500 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5501 {
5502 pAdapter = pAdapterNode->pAdapter;
5503 netif_tx_disable(pAdapter->dev);
5504 netif_carrier_off(pAdapter->dev);
5505
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005506 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
5507
Jeff Johnson295189b2012-06-20 16:38:30 -07005508 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305509 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5510 {
5511 hdd_wmm_adapter_close( pAdapter );
5512 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5513 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005514
5515 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5516 pAdapterNode = pNext;
5517 }
5518
5519 EXIT();
5520
5521 return VOS_STATUS_SUCCESS;
5522}
5523
5524VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
5525{
5526 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5527 VOS_STATUS status;
5528 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305529 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07005530
5531 ENTER();
5532
5533 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5534
5535 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5536 {
5537 pAdapter = pAdapterNode->pAdapter;
5538
5539 switch(pAdapter->device_mode)
5540 {
5541 case WLAN_HDD_INFRA_STATION:
5542 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005543 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305544
5545 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
5546
Jeff Johnson295189b2012-06-20 16:38:30 -07005547 hdd_init_station_mode(pAdapter);
5548 /* Open the gates for HDD to receive Wext commands */
5549 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005550 pHddCtx->scan_info.mScanPending = FALSE;
5551 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005552
5553 //Trigger the initial scan
5554 hdd_wlan_initial_scan(pAdapter);
5555
5556 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305557 if (eConnectionState_Associated == connState ||
5558 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07005559 {
5560 union iwreq_data wrqu;
5561 memset(&wrqu, '\0', sizeof(wrqu));
5562 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5563 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5564 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005565 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005566
Jeff Johnson295189b2012-06-20 16:38:30 -07005567 /* indicate disconnected event to nl80211 */
5568 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
5569 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005570 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305571 else if (eConnectionState_Connecting == connState)
5572 {
5573 /*
5574 * Indicate connect failure to supplicant if we were in the
5575 * process of connecting
5576 */
5577 cfg80211_connect_result(pAdapter->dev, NULL,
5578 NULL, 0, NULL, 0,
5579 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
5580 GFP_KERNEL);
5581 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005582 break;
5583
5584 case WLAN_HDD_SOFTAP:
5585 /* softAP can handle SSR */
5586 break;
5587
5588 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07005589 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07005590 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07005591 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005592 break;
5593
5594 case WLAN_HDD_MONITOR:
5595 /* monitor interface start */
5596 break;
5597 default:
5598 break;
5599 }
5600
5601 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5602 pAdapterNode = pNext;
5603 }
5604
5605 EXIT();
5606
5607 return VOS_STATUS_SUCCESS;
5608}
5609
5610VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
5611{
5612 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5613 hdd_adapter_t *pAdapter;
5614 VOS_STATUS status;
5615 v_U32_t roamId;
5616
5617 ENTER();
5618
5619 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5620
5621 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5622 {
5623 pAdapter = pAdapterNode->pAdapter;
5624
5625 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5626 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
5627 {
5628 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5629 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5630
5631 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5632 init_completion(&pAdapter->disconnect_comp_var);
5633 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
5634 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5635
5636 wait_for_completion_interruptible_timeout(
5637 &pAdapter->disconnect_comp_var,
5638 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5639
5640 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
5641 pHddCtx->isAmpAllowed = VOS_FALSE;
5642 sme_RoamConnect(pHddCtx->hHal,
5643 pAdapter->sessionId, &(pWextState->roamProfile),
5644 &roamId);
5645 }
5646
5647 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5648 pAdapterNode = pNext;
5649 }
5650
5651 EXIT();
5652
5653 return VOS_STATUS_SUCCESS;
5654}
5655
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07005656void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
5657{
5658 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5659 VOS_STATUS status;
5660 hdd_adapter_t *pAdapter;
5661 hdd_station_ctx_t *pHddStaCtx;
5662 hdd_ap_ctx_t *pHddApCtx;
5663 hdd_hostapd_state_t * pHostapdState;
5664 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
5665 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
5666 const char *p2pMode = "DEV";
5667 const char *ccMode = "Standalone";
5668 int n;
5669
5670 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5671 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5672 {
5673 pAdapter = pAdapterNode->pAdapter;
5674 switch (pAdapter->device_mode) {
5675 case WLAN_HDD_INFRA_STATION:
5676 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5677 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
5678 staChannel = pHddStaCtx->conn_info.operationChannel;
5679 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
5680 }
5681 break;
5682 case WLAN_HDD_P2P_CLIENT:
5683 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
5684 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
5685 p2pChannel = pHddStaCtx->conn_info.operationChannel;
5686 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
5687 p2pMode = "CLI";
5688 }
5689 break;
5690 case WLAN_HDD_P2P_GO:
5691 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
5692 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5693 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
5694 p2pChannel = pHddApCtx->operatingChannel;
5695 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
5696 }
5697 p2pMode = "GO";
5698 break;
5699 case WLAN_HDD_SOFTAP:
5700 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
5701 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5702 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
5703 apChannel = pHddApCtx->operatingChannel;
5704 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
5705 }
5706 break;
5707 default:
5708 break;
5709 }
5710 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5711 pAdapterNode = pNext;
5712 }
5713 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
5714 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
5715 }
5716 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
5717 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
5718 if (p2pChannel > 0) {
5719 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
5720 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
5721 }
5722 if (apChannel > 0) {
5723 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
5724 apChannel, MAC_ADDR_ARRAY(apBssid));
5725 }
5726
5727 if (p2pChannel > 0 && apChannel > 0) {
5728 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
5729 }
5730}
5731
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005732bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07005733{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005734 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07005735}
5736
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005737/* Once SSR is disabled then it cannot be set. */
5738void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07005739{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07005740 if (HDD_SSR_DISABLED == isSsrRequired)
5741 return;
5742
Jeff Johnson295189b2012-06-20 16:38:30 -07005743 isSsrRequired = value;
5744}
5745
5746VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
5747 hdd_adapter_list_node_t** ppAdapterNode)
5748{
5749 VOS_STATUS status;
5750 spin_lock(&pHddCtx->hddAdapters.lock);
5751 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
5752 (hdd_list_node_t**) ppAdapterNode );
5753 spin_unlock(&pHddCtx->hddAdapters.lock);
5754 return status;
5755}
5756
5757VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
5758 hdd_adapter_list_node_t* pAdapterNode,
5759 hdd_adapter_list_node_t** pNextAdapterNode)
5760{
5761 VOS_STATUS status;
5762 spin_lock(&pHddCtx->hddAdapters.lock);
5763 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
5764 (hdd_list_node_t*) pAdapterNode,
5765 (hdd_list_node_t**)pNextAdapterNode );
5766
5767 spin_unlock(&pHddCtx->hddAdapters.lock);
5768 return status;
5769}
5770
5771VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
5772 hdd_adapter_list_node_t* pAdapterNode)
5773{
5774 VOS_STATUS status;
5775 spin_lock(&pHddCtx->hddAdapters.lock);
5776 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
5777 &pAdapterNode->node );
5778 spin_unlock(&pHddCtx->hddAdapters.lock);
5779 return status;
5780}
5781
5782VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
5783 hdd_adapter_list_node_t** ppAdapterNode)
5784{
5785 VOS_STATUS status;
5786 spin_lock(&pHddCtx->hddAdapters.lock);
5787 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
5788 (hdd_list_node_t**) ppAdapterNode );
5789 spin_unlock(&pHddCtx->hddAdapters.lock);
5790 return status;
5791}
5792
5793VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
5794 hdd_adapter_list_node_t* pAdapterNode)
5795{
5796 VOS_STATUS status;
5797 spin_lock(&pHddCtx->hddAdapters.lock);
5798 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
5799 (hdd_list_node_t*) pAdapterNode );
5800 spin_unlock(&pHddCtx->hddAdapters.lock);
5801 return status;
5802}
5803
5804VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
5805 hdd_adapter_list_node_t* pAdapterNode)
5806{
5807 VOS_STATUS status;
5808 spin_lock(&pHddCtx->hddAdapters.lock);
5809 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
5810 (hdd_list_node_t*) pAdapterNode );
5811 spin_unlock(&pHddCtx->hddAdapters.lock);
5812 return status;
5813}
5814
5815hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
5816 tSirMacAddr macAddr )
5817{
5818 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5819 hdd_adapter_t *pAdapter;
5820 VOS_STATUS status;
5821
5822 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5823
5824 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5825 {
5826 pAdapter = pAdapterNode->pAdapter;
5827
5828 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
5829 macAddr, sizeof(tSirMacAddr) ) )
5830 {
5831 return pAdapter;
5832 }
5833 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5834 pAdapterNode = pNext;
5835 }
5836
5837 return NULL;
5838
5839}
5840
5841hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
5842{
5843 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5844 hdd_adapter_t *pAdapter;
5845 VOS_STATUS status;
5846
5847 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5848
5849 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5850 {
5851 pAdapter = pAdapterNode->pAdapter;
5852
5853 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
5854 IFNAMSIZ ) )
5855 {
5856 return pAdapter;
5857 }
5858 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5859 pAdapterNode = pNext;
5860 }
5861
5862 return NULL;
5863
5864}
5865
5866hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
5867{
5868 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5869 hdd_adapter_t *pAdapter;
5870 VOS_STATUS status;
5871
5872 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5873
5874 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5875 {
5876 pAdapter = pAdapterNode->pAdapter;
5877
5878 if( pAdapter && (mode == pAdapter->device_mode) )
5879 {
5880 return pAdapter;
5881 }
5882 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5883 pAdapterNode = pNext;
5884 }
5885
5886 return NULL;
5887
5888}
5889
5890//Remove this function later
5891hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
5892{
5893 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5894 hdd_adapter_t *pAdapter;
5895 VOS_STATUS status;
5896
5897 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5898
5899 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5900 {
5901 pAdapter = pAdapterNode->pAdapter;
5902
5903 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
5904 {
5905 return pAdapter;
5906 }
5907
5908 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5909 pAdapterNode = pNext;
5910 }
5911
5912 return NULL;
5913
5914}
5915
Jeff Johnson295189b2012-06-20 16:38:30 -07005916/**---------------------------------------------------------------------------
5917
5918 \brief hdd_set_monitor_tx_adapter() -
5919
5920 This API initializes the adapter to be used while transmitting on monitor
5921 adapter.
5922
5923 \param - pHddCtx - Pointer to the HDD context.
5924 pAdapter - Adapter that will used for TX. This can be NULL.
5925 \return - None.
5926 --------------------------------------------------------------------------*/
5927void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5928{
5929 hdd_adapter_t *pMonAdapter;
5930
5931 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
5932
5933 if( NULL != pMonAdapter )
5934 {
5935 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
5936 }
5937}
Jeff Johnson295189b2012-06-20 16:38:30 -07005938/**---------------------------------------------------------------------------
5939
5940 \brief hdd_select_queue() -
5941
5942 This API returns the operating channel of the requested device mode
5943
5944 \param - pHddCtx - Pointer to the HDD context.
5945 - mode - Device mode for which operating channel is required
5946 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
5947 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
5948 \return - channel number. "0" id the requested device is not found OR it is not connected.
5949 --------------------------------------------------------------------------*/
5950v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
5951{
5952 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5953 VOS_STATUS status;
5954 hdd_adapter_t *pAdapter;
5955 v_U8_t operatingChannel = 0;
5956
5957 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5958
5959 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5960 {
5961 pAdapter = pAdapterNode->pAdapter;
5962
5963 if( mode == pAdapter->device_mode )
5964 {
5965 switch(pAdapter->device_mode)
5966 {
5967 case WLAN_HDD_INFRA_STATION:
5968 case WLAN_HDD_P2P_CLIENT:
5969 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5970 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
5971 break;
5972 case WLAN_HDD_SOFTAP:
5973 case WLAN_HDD_P2P_GO:
5974 /*softap connection info */
5975 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5976 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
5977 break;
5978 default:
5979 break;
5980 }
5981
5982 break; //Found the device of interest. break the loop
5983 }
5984
5985 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5986 pAdapterNode = pNext;
5987 }
5988 return operatingChannel;
5989}
5990
5991#ifdef WLAN_FEATURE_PACKET_FILTERING
5992/**---------------------------------------------------------------------------
5993
5994 \brief hdd_set_multicast_list() -
5995
5996 This used to set the multicast address list.
5997
5998 \param - dev - Pointer to the WLAN device.
5999 - skb - Pointer to OS packet (sk_buff).
6000 \return - success/fail
6001
6002 --------------------------------------------------------------------------*/
6003static void hdd_set_multicast_list(struct net_device *dev)
6004{
6005 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006006 int mc_count;
6007 int i = 0;
6008 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306009
6010 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006011 {
6012 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306013 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006014 return;
6015 }
6016
6017 if (dev->flags & IFF_ALLMULTI)
6018 {
6019 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006020 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306021 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006022 }
6023 else
6024 {
6025 mc_count = netdev_mc_count(dev);
6026 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006027 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006028 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6029 {
6030 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006031 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306032 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006033 return;
6034 }
6035
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306036 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006037
6038 netdev_for_each_mc_addr(ha, dev) {
6039 if (i == mc_count)
6040 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306041 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6042 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6043 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006044 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306045 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006046 i++;
6047 }
6048 }
6049 return;
6050}
6051#endif
6052
6053/**---------------------------------------------------------------------------
6054
6055 \brief hdd_select_queue() -
6056
6057 This function is registered with the Linux OS for network
6058 core to decide which queue to use first.
6059
6060 \param - dev - Pointer to the WLAN device.
6061 - skb - Pointer to OS packet (sk_buff).
6062 \return - ac, Queue Index/access category corresponding to UP in IP header
6063
6064 --------------------------------------------------------------------------*/
6065v_U16_t hdd_select_queue(struct net_device *dev,
6066 struct sk_buff *skb)
6067{
6068 return hdd_wmm_select_queue(dev, skb);
6069}
6070
6071
6072/**---------------------------------------------------------------------------
6073
6074 \brief hdd_wlan_initial_scan() -
6075
6076 This function triggers the initial scan
6077
6078 \param - pAdapter - Pointer to the HDD adapter.
6079
6080 --------------------------------------------------------------------------*/
6081void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6082{
6083 tCsrScanRequest scanReq;
6084 tCsrChannelInfo channelInfo;
6085 eHalStatus halStatus;
6086 unsigned long scanId;
6087 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6088
6089 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6090 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6091 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6092
6093 if(sme_Is11dSupported(pHddCtx->hHal))
6094 {
6095 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6096 if ( HAL_STATUS_SUCCESS( halStatus ) )
6097 {
6098 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6099 if( !scanReq.ChannelInfo.ChannelList )
6100 {
6101 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6102 vos_mem_free(channelInfo.ChannelList);
6103 return;
6104 }
6105 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6106 channelInfo.numOfChannels);
6107 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6108 vos_mem_free(channelInfo.ChannelList);
6109 }
6110
6111 scanReq.scanType = eSIR_PASSIVE_SCAN;
6112 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6113 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6114 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6115 }
6116 else
6117 {
6118 scanReq.scanType = eSIR_ACTIVE_SCAN;
6119 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6120 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6121 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6122 }
6123
6124 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6125 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6126 {
6127 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6128 __func__, halStatus );
6129 }
6130
6131 if(sme_Is11dSupported(pHddCtx->hHal))
6132 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6133}
6134
6135struct fullPowerContext
6136{
6137 struct completion completion;
6138 unsigned int magic;
6139};
6140#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6141
6142/**---------------------------------------------------------------------------
6143
6144 \brief hdd_full_power_callback() - HDD full power callback function
6145
6146 This is the function invoked by SME to inform the result of a full power
6147 request issued by HDD
6148
6149 \param - callbackcontext - Pointer to cookie
6150 \param - status - result of request
6151
6152 \return - None
6153
6154 --------------------------------------------------------------------------*/
6155static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6156{
6157 struct fullPowerContext *pContext = callbackContext;
6158
6159 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306160 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006161
6162 if (NULL == callbackContext)
6163 {
6164 hddLog(VOS_TRACE_LEVEL_ERROR,
6165 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006166 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006167 return;
6168 }
6169
6170 /* there is a race condition that exists between this callback function
6171 and the caller since the caller could time out either before or
6172 while this code is executing. we'll assume the timeout hasn't
6173 occurred, but we'll verify that right before we save our work */
6174
6175 if (POWER_CONTEXT_MAGIC != pContext->magic)
6176 {
6177 /* the caller presumably timed out so there is nothing we can do */
6178 hddLog(VOS_TRACE_LEVEL_WARN,
6179 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006180 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 return;
6182 }
6183
6184 /* the race is on. caller could have timed out immediately after
6185 we verified the magic, but if so, caller will wait a short time
6186 for us to notify the caller, so the context will stay valid */
6187 complete(&pContext->completion);
6188}
6189
6190/**---------------------------------------------------------------------------
6191
6192 \brief hdd_wlan_exit() - HDD WLAN exit function
6193
6194 This is the driver exit point (invoked during rmmod)
6195
6196 \param - pHddCtx - Pointer to the HDD Context
6197
6198 \return - None
6199
6200 --------------------------------------------------------------------------*/
6201void hdd_wlan_exit(hdd_context_t *pHddCtx)
6202{
6203 eHalStatus halStatus;
6204 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6205 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306206 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006207 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006208 struct fullPowerContext powerContext;
6209 long lrc;
6210
6211 ENTER();
6212
Jeff Johnson88ba7742013-02-27 14:36:02 -08006213 if (VOS_FTM_MODE != hdd_get_conparam())
6214 {
6215 // Unloading, restart logic is no more required.
6216 wlan_hdd_restart_deinit(pHddCtx);
6217 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006218
Jeff Johnson295189b2012-06-20 16:38:30 -07006219 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006220 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006221 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006222 {
6223 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6224 WLAN_HDD_INFRA_STATION);
6225 if (pAdapter == NULL)
6226 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6227
6228 if (pAdapter != NULL)
6229 {
6230 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6231 hdd_UnregisterWext(pAdapter->dev);
6232 }
6233 }
6234 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006235
Jeff Johnson295189b2012-06-20 16:38:30 -07006236 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006237 {
6238 wlan_hdd_ftm_close(pHddCtx);
6239 goto free_hdd_ctx;
6240 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006241 //Stop the Interface TX queue.
6242 //netif_tx_disable(pWlanDev);
6243 //netif_carrier_off(pWlanDev);
6244
Jeff Johnson295189b2012-06-20 16:38:30 -07006245 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6246 {
6247 pAdapter = hdd_get_adapter(pHddCtx,
6248 WLAN_HDD_SOFTAP);
6249 }
6250 else
6251 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006252 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006253 {
6254 pAdapter = hdd_get_adapter(pHddCtx,
6255 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006256 if (pAdapter == NULL)
6257 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006258 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006259 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006260 /* DeRegister with platform driver as client for Suspend/Resume */
6261 vosStatus = hddDeregisterPmOps(pHddCtx);
6262 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6263 {
6264 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6265 VOS_ASSERT(0);
6266 }
6267
6268 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6269 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6270 {
6271 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6272 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006273
6274 // Cancel any outstanding scan requests. We are about to close all
6275 // of our adapters, but an adapter structure is what SME passes back
6276 // to our callback function. Hence if there are any outstanding scan
6277 // requests then there is a race condition between when the adapter
6278 // is closed and when the callback is invoked. We try to resolve that
6279 // race condition here by canceling any outstanding scans before we
6280 // close the adapters.
6281 // Note that the scans may be cancelled in an asynchronous manner, so
6282 // ideally there needs to be some kind of synchronization. Rather than
6283 // introduce a new synchronization here, we will utilize the fact that
6284 // we are about to Request Full Power, and since that is synchronized,
6285 // the expectation is that by the time Request Full Power has completed,
6286 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006287 if (NULL != pAdapter)
6288 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6289 else
6290 hddLog(VOS_TRACE_LEVEL_ERROR,
6291 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006292
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006293 //Stop the traffic monitor timer
6294 if ( VOS_TIMER_STATE_RUNNING ==
6295 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6296 {
6297 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6298 }
6299
6300 // Destroy the traffic monitor timer
6301 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
6302 &pHddCtx->tx_rx_trafficTmr)))
6303 {
6304 hddLog(VOS_TRACE_LEVEL_ERROR,
6305 "%s: Cannot deallocate Traffic monitor timer", __func__);
6306 }
6307
Jeff Johnson295189b2012-06-20 16:38:30 -07006308 //Disable IMPS/BMPS as we do not want the device to enter any power
6309 //save mode during shutdown
6310 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6311 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6312 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
6313
6314 //Ensure that device is in full power as we will touch H/W during vos_Stop
6315 init_completion(&powerContext.completion);
6316 powerContext.magic = POWER_CONTEXT_MAGIC;
6317
6318 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
6319 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
6320
6321 if (eHAL_STATUS_SUCCESS != halStatus)
6322 {
6323 if (eHAL_STATUS_PMC_PENDING == halStatus)
6324 {
6325 /* request was sent -- wait for the response */
6326 lrc = wait_for_completion_interruptible_timeout(
6327 &powerContext.completion,
6328 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
6329 /* either we have a response or we timed out
6330 either way, first invalidate our magic */
6331 powerContext.magic = 0;
6332 if (lrc <= 0)
6333 {
6334 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006335 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07006336 /* there is a race condition such that the callback
6337 function could be executing at the same time we are. of
6338 primary concern is if the callback function had already
6339 verified the "magic" but hasn't yet set the completion
6340 variable. Since the completion variable is on our
6341 stack, we'll delay just a bit to make sure the data is
6342 still valid if that is the case */
6343 msleep(50);
6344 }
6345 }
6346 else
6347 {
6348 hddLog(VOS_TRACE_LEVEL_ERROR,
6349 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006350 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07006351 VOS_ASSERT(0);
6352 /* continue -- need to clean up as much as possible */
6353 }
6354 }
6355
Yue Ma0d4891e2013-08-06 17:01:45 -07006356 hdd_debugfs_exit(pHddCtx);
6357
Jeff Johnson295189b2012-06-20 16:38:30 -07006358 // Unregister the Net Device Notifier
6359 unregister_netdevice_notifier(&hdd_netdev_notifier);
6360
Jeff Johnson295189b2012-06-20 16:38:30 -07006361 hdd_stop_all_adapters( pHddCtx );
6362
Jeff Johnson295189b2012-06-20 16:38:30 -07006363#ifdef WLAN_BTAMP_FEATURE
6364 vosStatus = WLANBAP_Stop(pVosContext);
6365 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6366 {
6367 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
6368 "%s: Failed to stop BAP",__func__);
6369 }
6370#endif //WLAN_BTAMP_FEATURE
6371
6372 //Stop all the modules
6373 vosStatus = vos_stop( pVosContext );
6374 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6375 {
6376 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6377 "%s: Failed to stop VOSS",__func__);
6378 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6379 }
6380
Jeff Johnson295189b2012-06-20 16:38:30 -07006381 //Assert Deep sleep signal now to put Libra HW in lowest power state
6382 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6383 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6384
6385 //Vote off any PMIC voltage supplies
6386 vos_chipPowerDown(NULL, NULL, NULL);
6387
6388 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
6389
Leo Chang59cdc7e2013-07-10 10:08:21 -07006390
Jeff Johnson295189b2012-06-20 16:38:30 -07006391 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07006392 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006393
6394 //Close the scheduler before calling vos_close to make sure no thread is
6395 // scheduled after the each module close is called i.e after all the data
6396 // structures are freed.
6397 vosStatus = vos_sched_close( pVosContext );
6398 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
6399 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6400 "%s: Failed to close VOSS Scheduler",__func__);
6401 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6402 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006403#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006404#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6405 /* Destroy the wake lock */
6406 wake_lock_destroy(&pHddCtx->rx_wake_lock);
6407#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006408 /* Destroy the wake lock */
6409 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006410#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006411
6412 //Close VOSS
6413 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
6414 vos_close(pVosContext);
6415
Jeff Johnson295189b2012-06-20 16:38:30 -07006416 //Close Watchdog
6417 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6418 vos_watchdog_close(pVosContext);
6419
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306420 //Clean up HDD Nlink Service
6421 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07006422#ifdef WLAN_KD_READY_NOTIFIER
6423 nl_srv_exit(pHddCtx->ptt_pid);
6424#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306425 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006426#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306427
Jeff Johnson295189b2012-06-20 16:38:30 -07006428 /* Cancel the vote for XO Core ON.
6429 * This is done here to ensure there is no race condition since MC, TX and WD threads have
6430 * exited at this point
6431 */
6432 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
6433 " when WLAN is turned OFF\n");
6434 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6435 {
6436 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
6437 " Not returning failure."
6438 " Power consumed will be high\n");
6439 }
6440
6441 hdd_close_all_adapters( pHddCtx );
6442
6443
6444 //Free up dynamically allocated members inside HDD Adapter
6445 kfree(pHddCtx->cfg_ini);
6446 pHddCtx->cfg_ini= NULL;
6447
6448 /* free the power on lock from platform driver */
6449 if (free_riva_power_on_lock("wlan"))
6450 {
6451 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
6452 __func__);
6453 }
6454
Jeff Johnson88ba7742013-02-27 14:36:02 -08006455free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07006456 /* FTM mode, WIPHY did not registered
6457 If un-register here, system crash will happen */
6458 if (VOS_FTM_MODE != hdd_get_conparam())
6459 {
6460 wiphy_unregister(wiphy) ;
6461 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006462 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006463 if (hdd_is_ssr_required())
6464 {
6465 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07006466 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07006467 msleep(5000);
6468 }
6469 hdd_set_ssr_required (VOS_FALSE);
6470}
6471
6472
6473/**---------------------------------------------------------------------------
6474
6475 \brief hdd_update_config_from_nv() - Function to update the contents of
6476 the running configuration with parameters taken from NV storage
6477
6478 \param - pHddCtx - Pointer to the HDD global context
6479
6480 \return - VOS_STATUS_SUCCESS if successful
6481
6482 --------------------------------------------------------------------------*/
6483static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
6484{
Jeff Johnson295189b2012-06-20 16:38:30 -07006485 v_BOOL_t itemIsValid = VOS_FALSE;
6486 VOS_STATUS status;
6487 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
6488 v_U8_t macLoop;
6489
6490 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
6491 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
6492 if(status != VOS_STATUS_SUCCESS)
6493 {
6494 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
6495 return VOS_STATUS_E_FAILURE;
6496 }
6497
6498 if (itemIsValid == VOS_TRUE)
6499 {
6500 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
6501 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
6502 VOS_MAX_CONCURRENCY_PERSONA);
6503 if(status != VOS_STATUS_SUCCESS)
6504 {
6505 /* Get MAC from NV fail, not update CFG info
6506 * INI MAC value will be used for MAC setting */
6507 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
6508 return VOS_STATUS_E_FAILURE;
6509 }
6510
6511 /* If first MAC is not valid, treat all others are not valid
6512 * Then all MACs will be got from ini file */
6513 if(vos_is_macaddr_zero(&macFromNV[0]))
6514 {
6515 /* MAC address in NV file is not configured yet */
6516 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
6517 return VOS_STATUS_E_INVAL;
6518 }
6519
6520 /* Get MAC address from NV, update CFG info */
6521 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
6522 {
6523 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
6524 {
6525 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
6526 /* This MAC is not valid, skip it
6527 * This MAC will be got from ini file */
6528 }
6529 else
6530 {
6531 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
6532 (v_U8_t *)&macFromNV[macLoop].bytes[0],
6533 VOS_MAC_ADDR_SIZE);
6534 }
6535 }
6536 }
6537 else
6538 {
6539 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
6540 return VOS_STATUS_E_FAILURE;
6541 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006542
Jeff Johnson295189b2012-06-20 16:38:30 -07006543
6544 return VOS_STATUS_SUCCESS;
6545}
6546
6547/**---------------------------------------------------------------------------
6548
6549 \brief hdd_post_voss_start_config() - HDD post voss start config helper
6550
6551 \param - pAdapter - Pointer to the HDD
6552
6553 \return - None
6554
6555 --------------------------------------------------------------------------*/
6556VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
6557{
6558 eHalStatus halStatus;
6559 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306560 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07006561
Jeff Johnson295189b2012-06-20 16:38:30 -07006562
6563 // Send ready indication to the HDD. This will kick off the MAC
6564 // into a 'running' state and should kick off an initial scan.
6565 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
6566 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6567 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306568 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07006569 "code %08d [x%08x]",__func__, halStatus, halStatus );
6570 return VOS_STATUS_E_FAILURE;
6571 }
6572
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306573 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07006574 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
6575 // And RIVA will crash
6576 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
6577 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306578 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
6579 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
6580
6581
Jeff Johnson295189b2012-06-20 16:38:30 -07006582 return VOS_STATUS_SUCCESS;
6583}
6584
Jeff Johnson295189b2012-06-20 16:38:30 -07006585/* wake lock APIs for HDD */
6586void hdd_prevent_suspend(void)
6587{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006588#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006589 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006590#else
6591 wcnss_prevent_suspend();
6592#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006593}
6594
6595void hdd_allow_suspend(void)
6596{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006597#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006598 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006599#else
6600 wcnss_allow_suspend();
6601#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006602}
6603
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07006604void hdd_allow_suspend_timeout(v_U32_t timeout)
6605{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006606#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07006607 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07006608#else
6609 /* Do nothing as there is no API in wcnss for timeout*/
6610#endif
6611}
6612
Jeff Johnson295189b2012-06-20 16:38:30 -07006613/**---------------------------------------------------------------------------
6614
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006615 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
6616 information between Host and Riva
6617
6618 This function gets reported version of FW
6619 It also finds the version of Riva headers used to compile the host
6620 It compares the above two and prints a warning if they are different
6621 It gets the SW and HW version string
6622 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
6623 indicating the features they support through a bitmap
6624
6625 \param - pHddCtx - Pointer to HDD context
6626
6627 \return - void
6628
6629 --------------------------------------------------------------------------*/
6630
6631void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
6632{
6633
6634 tSirVersionType versionCompiled;
6635 tSirVersionType versionReported;
6636 tSirVersionString versionString;
6637 tANI_U8 fwFeatCapsMsgSupported = 0;
6638 VOS_STATUS vstatus;
6639
6640 /* retrieve and display WCNSS version information */
6641 do {
6642
6643 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
6644 &versionCompiled);
6645 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6646 {
6647 hddLog(VOS_TRACE_LEVEL_FATAL,
6648 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006649 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006650 break;
6651 }
6652
6653 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
6654 &versionReported);
6655 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6656 {
6657 hddLog(VOS_TRACE_LEVEL_FATAL,
6658 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006659 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006660 break;
6661 }
6662
6663 if ((versionCompiled.major != versionReported.major) ||
6664 (versionCompiled.minor != versionReported.minor) ||
6665 (versionCompiled.version != versionReported.version) ||
6666 (versionCompiled.revision != versionReported.revision))
6667 {
6668 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
6669 "Host expected %u.%u.%u.%u\n",
6670 WLAN_MODULE_NAME,
6671 (int)versionReported.major,
6672 (int)versionReported.minor,
6673 (int)versionReported.version,
6674 (int)versionReported.revision,
6675 (int)versionCompiled.major,
6676 (int)versionCompiled.minor,
6677 (int)versionCompiled.version,
6678 (int)versionCompiled.revision);
6679 }
6680 else
6681 {
6682 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
6683 WLAN_MODULE_NAME,
6684 (int)versionReported.major,
6685 (int)versionReported.minor,
6686 (int)versionReported.version,
6687 (int)versionReported.revision);
6688 }
6689
6690 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
6691 versionString,
6692 sizeof(versionString));
6693 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6694 {
6695 hddLog(VOS_TRACE_LEVEL_FATAL,
6696 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006697 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006698 break;
6699 }
6700
6701 pr_info("%s: WCNSS software version %s\n",
6702 WLAN_MODULE_NAME, versionString);
6703
6704 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
6705 versionString,
6706 sizeof(versionString));
6707 if (!VOS_IS_STATUS_SUCCESS(vstatus))
6708 {
6709 hddLog(VOS_TRACE_LEVEL_FATAL,
6710 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006711 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006712 break;
6713 }
6714
6715 pr_info("%s: WCNSS hardware version %s\n",
6716 WLAN_MODULE_NAME, versionString);
6717
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006718 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
6719 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006720 send the message only if it the riva is 1.1
6721 minor numbers for different riva branches:
6722 0 -> (1.0)Mainline Build
6723 1 -> (1.1)Mainline Build
6724 2->(1.04) Stability Build
6725 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006726 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006727 ((versionReported.minor>=1) && (versionReported.version>=1)))
6728 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
6729 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07006730
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006731 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08006732 {
6733#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
6734 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
6735 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
6736#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07006737 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
6738 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
6739 {
6740 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
6741 }
6742
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006743 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08006744 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006745
6746 } while (0);
6747
6748}
6749
6750/**---------------------------------------------------------------------------
6751
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05306752 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
6753
6754 \param - pHddCtx - Pointer to the hdd context
6755
6756 \return - true if hardware supports 5GHz
6757
6758 --------------------------------------------------------------------------*/
6759static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
6760{
6761 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
6762 * then hardware support 5Ghz.
6763 */
6764 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
6765 {
6766 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
6767 return true;
6768 }
6769 else
6770 {
6771 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
6772 __func__);
6773 return false;
6774 }
6775}
6776
6777
6778/**---------------------------------------------------------------------------
6779
Jeff Johnson295189b2012-06-20 16:38:30 -07006780 \brief hdd_wlan_startup() - HDD init function
6781
6782 This is the driver startup code executed once a WLAN device has been detected
6783
6784 \param - dev - Pointer to the underlying device
6785
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006786 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07006787
6788 --------------------------------------------------------------------------*/
6789
6790int hdd_wlan_startup(struct device *dev )
6791{
6792 VOS_STATUS status;
6793 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07006794 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006795 hdd_context_t *pHddCtx = NULL;
6796 v_CONTEXT_t pVosContext= NULL;
6797#ifdef WLAN_BTAMP_FEATURE
6798 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
6799 WLANBAP_ConfigType btAmpConfig;
6800 hdd_config_t *pConfig;
6801#endif
6802 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006803 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006804
6805 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07006806 /*
6807 * cfg80211: wiphy allocation
6808 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306809 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006810
6811 if(wiphy == NULL)
6812 {
6813 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08006814 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07006815 }
6816
6817 pHddCtx = wiphy_priv(wiphy);
6818
Jeff Johnson295189b2012-06-20 16:38:30 -07006819 //Initialize the adapter context to zeros.
6820 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
6821
Jeff Johnson295189b2012-06-20 16:38:30 -07006822 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006823 hdd_prevent_suspend();
6824 pHddCtx->isLoadUnloadInProgress = TRUE;
6825
6826 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
6827
6828 /*Get vos context here bcoz vos_open requires it*/
6829 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
6830
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08006831 if(pVosContext == NULL)
6832 {
6833 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
6834 goto err_free_hdd_context;
6835 }
6836
Jeff Johnson295189b2012-06-20 16:38:30 -07006837 //Save the Global VOSS context in adapter context for future.
6838 pHddCtx->pvosContext = pVosContext;
6839
6840 //Save the adapter context in global context for future.
6841 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
6842
Jeff Johnson295189b2012-06-20 16:38:30 -07006843 pHddCtx->parent_dev = dev;
6844
6845 init_completion(&pHddCtx->full_pwr_comp_var);
6846 init_completion(&pHddCtx->standby_comp_var);
6847 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006848 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08006849 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07006850
6851#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07006852 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07006853#else
6854 init_completion(&pHddCtx->driver_crda_req);
6855#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006856
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05306857 spin_lock_init(&pHddCtx->schedScan_lock);
6858
Jeff Johnson295189b2012-06-20 16:38:30 -07006859 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
6860
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306861#ifdef FEATURE_WLAN_TDLS
6862 /* tdls_lock is initialized before an hdd_open_adapter ( which is
6863 * invoked by other instances also) to protect the concurrent
6864 * access for the Adapters by TDLS module.
6865 */
6866 mutex_init(&pHddCtx->tdls_lock);
6867#endif
6868
Jeff Johnson295189b2012-06-20 16:38:30 -07006869 // Load all config first as TL config is needed during vos_open
6870 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
6871 if(pHddCtx->cfg_ini == NULL)
6872 {
6873 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
6874 goto err_free_hdd_context;
6875 }
6876
6877 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
6878
6879 // Read and parse the qcom_cfg.ini file
6880 status = hdd_parse_config_ini( pHddCtx );
6881 if ( VOS_STATUS_SUCCESS != status )
6882 {
6883 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
6884 __func__, WLAN_INI_FILE);
6885 goto err_config;
6886 }
6887
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05306888 /* INI has been read, initialise the configuredMcastBcastFilter with
6889 * INI value as this will serve as the default value
6890 */
6891 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
6892 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
6893 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05306894
6895 if (false == hdd_is_5g_supported(pHddCtx))
6896 {
6897 //5Ghz is not supported.
6898 if (1 != pHddCtx->cfg_ini->nBandCapability)
6899 {
6900 hddLog(VOS_TRACE_LEVEL_INFO,
6901 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
6902 pHddCtx->cfg_ini->nBandCapability = 1;
6903 }
6904 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05306905
6906 /* If SNR Monitoring is enabled, FW has to parse all beacons
6907 * for calcaluting and storing the average SNR, so set Nth beacon
6908 * filter to 1 to enable FW to parse all the beaocons
6909 */
6910 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
6911 {
6912 /* The log level is deliberately set to WARN as overriding
6913 * nthBeaconFilter to 1 will increase power cosumption and this
6914 * might just prove helpful to detect the power issue.
6915 */
6916 hddLog(VOS_TRACE_LEVEL_WARN,
6917 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
6918 pHddCtx->cfg_ini->nthBeaconFilter = 1;
6919 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006920 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306921 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07006922 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306923 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07006924 {
6925 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306926 "%s: wlan_hdd_cfg80211_init return failure", __func__);
6927 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07006928 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006929
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006930 // Update VOS trace levels based upon the cfg.ini
6931 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
6932 pHddCtx->cfg_ini->vosTraceEnableBAP);
6933 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
6934 pHddCtx->cfg_ini->vosTraceEnableTL);
6935 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
6936 pHddCtx->cfg_ini->vosTraceEnableWDI);
6937 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
6938 pHddCtx->cfg_ini->vosTraceEnableHDD);
6939 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
6940 pHddCtx->cfg_ini->vosTraceEnableSME);
6941 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
6942 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05306943 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
6944 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006945 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
6946 pHddCtx->cfg_ini->vosTraceEnableWDA);
6947 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
6948 pHddCtx->cfg_ini->vosTraceEnableSYS);
6949 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
6950 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006951 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
6952 pHddCtx->cfg_ini->vosTraceEnableSAP);
6953 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
6954 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08006955
Jeff Johnson295189b2012-06-20 16:38:30 -07006956 // Update WDI trace levels based upon the cfg.ini
6957 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
6958 pHddCtx->cfg_ini->wdiTraceEnableDAL);
6959 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
6960 pHddCtx->cfg_ini->wdiTraceEnableCTL);
6961 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
6962 pHddCtx->cfg_ini->wdiTraceEnableDAT);
6963 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
6964 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006965
Jeff Johnson88ba7742013-02-27 14:36:02 -08006966 if (VOS_FTM_MODE == hdd_get_conparam())
6967 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006968 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
6969 {
6970 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
6971 goto err_free_hdd_context;
6972 }
6973 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
6974 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08006975 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006976
Jeff Johnson88ba7742013-02-27 14:36:02 -08006977 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07006978 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6979 {
6980 status = vos_watchdog_open(pVosContext,
6981 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
6982
6983 if(!VOS_IS_STATUS_SUCCESS( status ))
6984 {
6985 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05306986 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07006987 }
6988 }
6989
6990 pHddCtx->isLogpInProgress = FALSE;
6991 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
6992
Jeff Johnson295189b2012-06-20 16:38:30 -07006993 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
6994 if(!VOS_IS_STATUS_SUCCESS(status))
6995 {
6996 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006997 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07006998 }
6999
Amar Singhala49cbc52013-10-08 18:37:44 -07007000#ifdef CONFIG_ENABLE_LINUX_REG
7001 /* registration of wiphy dev with cfg80211 */
7002 if (0 > wlan_hdd_cfg80211_register(wiphy))
7003 {
7004 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7005 goto err_clkvote;
7006 }
7007#endif
7008
Jeff Johnson295189b2012-06-20 16:38:30 -07007009 status = vos_open( &pVosContext, 0);
7010 if ( !VOS_IS_STATUS_SUCCESS( status ))
7011 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007012 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007013 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007014 }
7015
Jeff Johnson295189b2012-06-20 16:38:30 -07007016 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7017
7018 if ( NULL == pHddCtx->hHal )
7019 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007020 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007021 goto err_vosclose;
7022 }
7023
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007024 status = vos_preStart( pHddCtx->pvosContext );
7025 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7026 {
7027 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7028 goto err_vosclose;
7029 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007030
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007031 /* Note that the vos_preStart() sequence triggers the cfg download.
7032 The cfg download must occur before we update the SME config
7033 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007034 status = hdd_set_sme_config( pHddCtx );
7035
7036 if ( VOS_STATUS_SUCCESS != status )
7037 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007038 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7039 goto err_vosclose;
7040 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007041
7042 //Initialize the WMM module
7043 status = hdd_wmm_init(pHddCtx);
7044 if (!VOS_IS_STATUS_SUCCESS(status))
7045 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007046 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007047 goto err_vosclose;
7048 }
7049
Jeff Johnson295189b2012-06-20 16:38:30 -07007050 /* In the integrated architecture we update the configuration from
7051 the INI file and from NV before vOSS has been started so that
7052 the final contents are available to send down to the cCPU */
7053
7054 // Apply the cfg.ini to cfg.dat
7055 if (FALSE == hdd_update_config_dat(pHddCtx))
7056 {
7057 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7058 goto err_vosclose;
7059 }
7060
7061 // Apply the NV to cfg.dat
7062 /* Prima Update MAC address only at here */
7063 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7064 {
7065#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7066 /* There was not a valid set of MAC Addresses in NV. See if the
7067 default addresses were modified by the cfg.ini settings. If so,
7068 we'll use them, but if not, we'll autogenerate a set of MAC
7069 addresses based upon the device serial number */
7070
7071 static const v_MACADDR_t default_address =
7072 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7073 unsigned int serialno;
7074 int i;
7075
7076 serialno = wcnss_get_serial_number();
7077 if ((0 != serialno) &&
7078 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7079 sizeof(default_address))))
7080 {
7081 /* cfg.ini has the default address, invoke autogen logic */
7082
7083 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7084 bytes of the serial number that can be used to generate
7085 the other 3 bytes of the MAC address. Mask off all but
7086 the lower 3 bytes (this will also make sure we don't
7087 overflow in the next step) */
7088 serialno &= 0x00FFFFFF;
7089
7090 /* we need a unique address for each session */
7091 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7092
7093 /* autogen all addresses */
7094 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7095 {
7096 /* start with the entire default address */
7097 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7098 /* then replace the lower 3 bytes */
7099 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7100 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7101 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7102
7103 serialno++;
7104 }
7105
7106 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7107 MAC_ADDRESS_STR,
7108 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7109 }
7110 else
7111#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7112 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007113 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007114 "%s: Invalid MAC address in NV, using MAC from ini file "
7115 MAC_ADDRESS_STR, __func__,
7116 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7117 }
7118 }
7119 {
7120 eHalStatus halStatus;
7121 // Set the MAC Address
7122 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7123 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7124 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7125 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7126
7127 if (!HAL_STATUS_SUCCESS( halStatus ))
7128 {
7129 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7130 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007131 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007132 }
7133 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007134
7135 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7136 Note: Firmware image will be read and downloaded inside vos_start API */
7137 status = vos_start( pHddCtx->pvosContext );
7138 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7139 {
7140 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7141 goto err_vosclose;
7142 }
7143
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007144 /* Exchange capability info between Host and FW and also get versioning info from FW */
7145 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007146
7147 status = hdd_post_voss_start_config( pHddCtx );
7148 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7149 {
7150 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7151 __func__);
7152 goto err_vosstop;
7153 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007154
7155#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307156 wlan_hdd_cfg80211_update_reg_info( wiphy );
7157
7158 /* registration of wiphy dev with cfg80211 */
7159 if (0 > wlan_hdd_cfg80211_register(wiphy))
7160 {
7161 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7162 goto err_vosstop;
7163 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007164#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007165
Jeff Johnson295189b2012-06-20 16:38:30 -07007166 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7167 {
7168 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7169 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7170 }
7171 else
7172 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007173 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7174 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7175 if (pAdapter != NULL)
7176 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307177 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007178 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307179 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7180 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7181 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007182
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307183 /* Generate the P2P Device Address. This consists of the device's
7184 * primary MAC address with the locally administered bit set.
7185 */
7186 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007187 }
7188 else
7189 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307190 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7191 if (p2p_dev_addr != NULL)
7192 {
7193 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7194 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7195 }
7196 else
7197 {
7198 hddLog(VOS_TRACE_LEVEL_FATAL,
7199 "%s: Failed to allocate mac_address for p2p_device",
7200 __func__);
7201 goto err_close_adapter;
7202 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007203 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007204
7205 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7206 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7207 if ( NULL == pP2pAdapter )
7208 {
7209 hddLog(VOS_TRACE_LEVEL_FATAL,
7210 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007211 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007212 goto err_close_adapter;
7213 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007214 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007215 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007216
7217 if( pAdapter == NULL )
7218 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007219 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7220 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007221 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007222
Jeff Johnson295189b2012-06-20 16:38:30 -07007223#ifdef WLAN_BTAMP_FEATURE
7224 vStatus = WLANBAP_Open(pVosContext);
7225 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7226 {
7227 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7228 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007229 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007230 }
7231
7232 vStatus = BSL_Init(pVosContext);
7233 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7234 {
7235 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7236 "%s: Failed to Init BSL",__func__);
7237 goto err_bap_close;
7238 }
7239 vStatus = WLANBAP_Start(pVosContext);
7240 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7241 {
7242 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7243 "%s: Failed to start TL",__func__);
7244 goto err_bap_close;
7245 }
7246
7247 pConfig = pHddCtx->cfg_ini;
7248 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7249 status = WLANBAP_SetConfig(&btAmpConfig);
7250
7251#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007252
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007253#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7254 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7255 {
7256 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7257 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7258 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7259 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7260 }
7261#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007262#ifdef FEATURE_WLAN_SCAN_PNO
7263 /*SME must send channel update configuration to RIVA*/
7264 sme_UpdateChannelConfig(pHddCtx->hHal);
7265#endif
7266
Jeff Johnson295189b2012-06-20 16:38:30 -07007267 /* Register with platform driver as client for Suspend/Resume */
7268 status = hddRegisterPmOps(pHddCtx);
7269 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7270 {
7271 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7272#ifdef WLAN_BTAMP_FEATURE
7273 goto err_bap_stop;
7274#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007275 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007276#endif //WLAN_BTAMP_FEATURE
7277 }
7278
Yue Ma0d4891e2013-08-06 17:01:45 -07007279 /* Open debugfs interface */
7280 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
7281 {
7282 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7283 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07007284 }
7285
Jeff Johnson295189b2012-06-20 16:38:30 -07007286 /* Register TM level change handler function to the platform */
7287 status = hddDevTmRegisterNotifyCallback(pHddCtx);
7288 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7289 {
7290 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
7291 goto err_unregister_pmops;
7292 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007293
7294 /* register for riva power on lock to platform driver */
7295 if (req_riva_power_on_lock("wlan"))
7296 {
7297 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
7298 __func__);
7299 goto err_unregister_pmops;
7300 }
7301
Jeff Johnson295189b2012-06-20 16:38:30 -07007302 // register net device notifier for device change notification
7303 ret = register_netdevice_notifier(&hdd_netdev_notifier);
7304
7305 if(ret < 0)
7306 {
7307 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
7308 goto err_free_power_on_lock;
7309 }
7310
7311 //Initialize the nlink service
7312 if(nl_srv_init() != 0)
7313 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307314 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007315 goto err_reg_netdev;
7316 }
7317
7318 //Initialize the BTC service
7319 if(btc_activate_service(pHddCtx) != 0)
7320 {
7321 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
7322 goto err_nl_srv;
7323 }
7324
7325#ifdef PTT_SOCK_SVC_ENABLE
7326 //Initialize the PTT service
7327 if(ptt_sock_activate_svc(pHddCtx) != 0)
7328 {
7329 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
7330 goto err_nl_srv;
7331 }
7332#endif
7333
Jeff Johnson295189b2012-06-20 16:38:30 -07007334 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007335 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007336 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07007337 /* Action frame registered in one adapter which will
7338 * applicable to all interfaces
7339 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07007340 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007341 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007342
7343 mutex_init(&pHddCtx->sap_lock);
7344
7345 pHddCtx->isLoadUnloadInProgress = FALSE;
7346
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007347#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007348#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7349 /* Initialize the wake lcok */
7350 wake_lock_init(&pHddCtx->rx_wake_lock,
7351 WAKE_LOCK_SUSPEND,
7352 "qcom_rx_wakelock");
7353#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007354 /* Initialize the wake lcok */
7355 wake_lock_init(&pHddCtx->sap_wake_lock,
7356 WAKE_LOCK_SUSPEND,
7357 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007358#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007359
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007360 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
7361 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07007362
7363 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7364 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05307365
Jeff Johnsone7245742012-09-05 17:12:55 -07007366 // Initialize the restart logic
7367 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05307368
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007369 //Register the traffic monitor timer now
7370 if ( pHddCtx->cfg_ini->dynSplitscan)
7371 {
7372 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
7373 VOS_TIMER_TYPE_SW,
7374 hdd_tx_rx_pkt_cnt_stat_timer_handler,
7375 (void *)pHddCtx);
7376 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007377 goto success;
7378
7379err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07007380#ifdef WLAN_KD_READY_NOTIFIER
7381 nl_srv_exit(pHddCtx->ptt_pid);
7382#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007383 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007384#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07007385err_reg_netdev:
7386 unregister_netdevice_notifier(&hdd_netdev_notifier);
7387
7388err_free_power_on_lock:
7389 free_riva_power_on_lock("wlan");
7390
7391err_unregister_pmops:
7392 hddDevTmUnregisterNotifyCallback(pHddCtx);
7393 hddDeregisterPmOps(pHddCtx);
7394
Yue Ma0d4891e2013-08-06 17:01:45 -07007395 hdd_debugfs_exit(pHddCtx);
7396
Jeff Johnson295189b2012-06-20 16:38:30 -07007397#ifdef WLAN_BTAMP_FEATURE
7398err_bap_stop:
7399 WLANBAP_Stop(pVosContext);
7400#endif
7401
7402#ifdef WLAN_BTAMP_FEATURE
7403err_bap_close:
7404 WLANBAP_Close(pVosContext);
7405#endif
7406
Jeff Johnson295189b2012-06-20 16:38:30 -07007407err_close_adapter:
7408 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07007409
7410#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307411 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07007412#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007413
7414err_vosstop:
7415 vos_stop(pVosContext);
7416
Amar Singhala49cbc52013-10-08 18:37:44 -07007417err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07007418 status = vos_sched_close( pVosContext );
7419 if (!VOS_IS_STATUS_SUCCESS(status)) {
7420 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7421 "%s: Failed to close VOSS Scheduler", __func__);
7422 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
7423 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007424 vos_close(pVosContext );
7425
7426err_wiphy_unregister:
7427
7428#ifdef CONFIG_ENABLE_LINUX_REG
7429 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07007430
Jeff Johnson295189b2012-06-20 16:38:30 -07007431err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07007432#endif
7433
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007434 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007435
7436err_wdclose:
7437 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7438 vos_watchdog_close(pVosContext);
7439
Jeff Johnson295189b2012-06-20 16:38:30 -07007440err_config:
7441 kfree(pHddCtx->cfg_ini);
7442 pHddCtx->cfg_ini= NULL;
7443
7444err_free_hdd_context:
7445 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07007446 wiphy_free(wiphy) ;
7447 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007448 VOS_BUG(1);
7449
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08007450 if (hdd_is_ssr_required())
7451 {
7452 /* WDI timeout had happened during load, so SSR is needed here */
7453 subsystem_restart("wcnss");
7454 msleep(5000);
7455 }
7456 hdd_set_ssr_required (VOS_FALSE);
7457
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007458 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007459
7460success:
7461 EXIT();
7462 return 0;
7463}
7464
7465/**---------------------------------------------------------------------------
7466
Jeff Johnson32d95a32012-09-10 13:15:23 -07007467 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07007468
Jeff Johnson32d95a32012-09-10 13:15:23 -07007469 This is the driver entry point - called in different timeline depending
7470 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07007471
7472 \param - None
7473
7474 \return - 0 for success, non zero for failure
7475
7476 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07007477static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007478{
7479 VOS_STATUS status;
7480 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007481 struct device *dev = NULL;
7482 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007483#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7484 int max_retries = 0;
7485#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007486
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307487#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7488 vos_wconn_trace_init();
7489#endif
7490
Jeff Johnson295189b2012-06-20 16:38:30 -07007491 ENTER();
7492
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007493#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007494 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07007495#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007496
7497 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
7498 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
7499
7500 //Power Up Libra WLAN card first if not already powered up
7501 status = vos_chipPowerUp(NULL,NULL,NULL);
7502 if (!VOS_IS_STATUS_SUCCESS(status))
7503 {
7504 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
7505 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307506#ifdef WLAN_OPEN_SOURCE
7507 wake_lock_destroy(&wlan_wake_lock);
7508#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007509 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007510 }
7511
Jeff Johnson295189b2012-06-20 16:38:30 -07007512#ifdef ANI_BUS_TYPE_PCI
7513
7514 dev = wcnss_wlan_get_device();
7515
7516#endif // ANI_BUS_TYPE_PCI
7517
7518#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007519
7520#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7521 /* wait until WCNSS driver downloads NV */
7522 while (!wcnss_device_ready() && 5 >= ++max_retries) {
7523 msleep(1000);
7524 }
7525 if (max_retries >= 5) {
7526 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307527#ifdef WLAN_OPEN_SOURCE
7528 wake_lock_destroy(&wlan_wake_lock);
7529#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007530 return -ENODEV;
7531 }
7532#endif
7533
Jeff Johnson295189b2012-06-20 16:38:30 -07007534 dev = wcnss_wlan_get_device();
7535#endif // ANI_BUS_TYPE_PLATFORM
7536
7537
7538 do {
7539 if (NULL == dev) {
7540 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
7541 ret_status = -1;
7542 break;
7543 }
7544
7545#ifdef MEMORY_DEBUG
7546 vos_mem_init();
7547#endif
7548
7549#ifdef TIMER_MANAGER
7550 vos_timer_manager_init();
7551#endif
7552
7553 /* Preopen VOSS so that it is ready to start at least SAL */
7554 status = vos_preOpen(&pVosContext);
7555
7556 if (!VOS_IS_STATUS_SUCCESS(status))
7557 {
7558 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
7559 ret_status = -1;
7560 break;
7561 }
7562
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007563#ifndef MODULE
7564 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
7565 */
7566 hdd_set_conparam((v_UINT_t)con_mode);
7567#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007568
7569 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007570 if (hdd_wlan_startup(dev))
7571 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007572 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007573 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007574 vos_preClose( &pVosContext );
7575 ret_status = -1;
7576 break;
7577 }
7578
7579 /* Cancel the vote for XO Core ON
7580 * This is done here for safety purposes in case we re-initialize without turning
7581 * it OFF in any error scenario.
7582 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007583 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07007584 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007585 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07007586 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7587 {
7588 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
7589 " Power consumed will be high\n");
7590 }
7591 } while (0);
7592
7593 if (0 != ret_status)
7594 {
7595 //Assert Deep sleep signal now to put Libra HW in lowest power state
7596 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7597 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
7598
7599 //Vote off any PMIC voltage supplies
7600 vos_chipPowerDown(NULL, NULL, NULL);
7601#ifdef TIMER_MANAGER
7602 vos_timer_exit();
7603#endif
7604#ifdef MEMORY_DEBUG
7605 vos_mem_exit();
7606#endif
7607
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007608#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007609 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007610#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007611 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
7612 }
7613 else
7614 {
7615 //Send WLAN UP indication to Nlink Service
7616 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
7617
7618 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07007619 }
7620
7621 EXIT();
7622
7623 return ret_status;
7624}
7625
Jeff Johnson32d95a32012-09-10 13:15:23 -07007626/**---------------------------------------------------------------------------
7627
7628 \brief hdd_module_init() - Init Function
7629
7630 This is the driver entry point (invoked when module is loaded using insmod)
7631
7632 \param - None
7633
7634 \return - 0 for success, non zero for failure
7635
7636 --------------------------------------------------------------------------*/
7637#ifdef MODULE
7638static int __init hdd_module_init ( void)
7639{
7640 return hdd_driver_init();
7641}
Jeff Johnson32d95a32012-09-10 13:15:23 -07007642#else /* #ifdef MODULE */
7643static int __init hdd_module_init ( void)
7644{
7645 /* Driver initialization is delayed to fwpath_changed_handler */
7646 return 0;
7647}
Jeff Johnson32d95a32012-09-10 13:15:23 -07007648#endif /* #ifdef MODULE */
7649
Jeff Johnson295189b2012-06-20 16:38:30 -07007650
7651/**---------------------------------------------------------------------------
7652
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007653 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07007654
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007655 This is the driver exit point (invoked when module is unloaded using rmmod
7656 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07007657
7658 \param - None
7659
7660 \return - None
7661
7662 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007663static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007664{
7665 hdd_context_t *pHddCtx = NULL;
7666 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007667 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007668
7669 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
7670
7671 //Get the global vos context
7672 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7673
7674 if(!pVosContext)
7675 {
7676 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
7677 goto done;
7678 }
7679
7680 //Get the HDD context.
7681 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
7682
7683 if(!pHddCtx)
7684 {
7685 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
7686 }
7687 else
7688 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007689 while(isWDresetInProgress()) {
7690 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7691 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007692 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07007693
7694 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
7695 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7696 "%s:SSR never completed, fatal error", __func__);
7697 VOS_BUG(0);
7698 }
7699 }
7700
Jeff Johnson295189b2012-06-20 16:38:30 -07007701
7702 pHddCtx->isLoadUnloadInProgress = TRUE;
7703 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7704
7705 //Do all the cleanup before deregistering the driver
7706 hdd_wlan_exit(pHddCtx);
7707 }
7708
Jeff Johnson295189b2012-06-20 16:38:30 -07007709 vos_preClose( &pVosContext );
7710
7711#ifdef TIMER_MANAGER
7712 vos_timer_exit();
7713#endif
7714#ifdef MEMORY_DEBUG
7715 vos_mem_exit();
7716#endif
7717
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307718#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7719 vos_wconn_trace_exit();
7720#endif
7721
Jeff Johnson295189b2012-06-20 16:38:30 -07007722done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007723#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007724 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007725#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007726 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
7727}
7728
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007729/**---------------------------------------------------------------------------
7730
7731 \brief hdd_module_exit() - Exit function
7732
7733 This is the driver exit point (invoked when module is unloaded using rmmod)
7734
7735 \param - None
7736
7737 \return - None
7738
7739 --------------------------------------------------------------------------*/
7740static void __exit hdd_module_exit(void)
7741{
7742 hdd_driver_exit();
7743}
7744
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007745#ifdef MODULE
7746static int fwpath_changed_handler(const char *kmessage,
7747 struct kernel_param *kp)
7748{
Jeff Johnson76052702013-04-16 13:55:05 -07007749 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007750}
7751
7752static int con_mode_handler(const char *kmessage,
7753 struct kernel_param *kp)
7754{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07007755 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007756}
7757#else /* #ifdef MODULE */
7758/**---------------------------------------------------------------------------
7759
Jeff Johnson76052702013-04-16 13:55:05 -07007760 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007761
Jeff Johnson76052702013-04-16 13:55:05 -07007762 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007763 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07007764 - invoked when module parameter fwpath is modified from userspace to signal
7765 initializing the WLAN driver or when con_mode is modified from userspace
7766 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007767
7768 \return - 0 for success, non zero for failure
7769
7770 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07007771static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007772{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007773 int ret_status;
7774
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007775 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007776 ret_status = hdd_driver_init();
7777 wlan_hdd_inited = ret_status ? 0 : 1;
7778 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007779 }
7780
7781 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07007782
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007783 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07007784
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07007785 ret_status = hdd_driver_init();
7786 wlan_hdd_inited = ret_status ? 0 : 1;
7787 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07007788}
7789
Jeff Johnson295189b2012-06-20 16:38:30 -07007790/**---------------------------------------------------------------------------
7791
Jeff Johnson76052702013-04-16 13:55:05 -07007792 \brief fwpath_changed_handler() - Handler Function
7793
7794 Handle changes to the fwpath parameter
7795
7796 \return - 0 for success, non zero for failure
7797
7798 --------------------------------------------------------------------------*/
7799static int fwpath_changed_handler(const char *kmessage,
7800 struct kernel_param *kp)
7801{
7802 int ret;
7803
7804 ret = param_set_copystring(kmessage, kp);
7805 if (0 == ret)
7806 ret = kickstart_driver();
7807 return ret;
7808}
7809
7810/**---------------------------------------------------------------------------
7811
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007812 \brief con_mode_handler() -
7813
7814 Handler function for module param con_mode when it is changed by userspace
7815 Dynamically linked - do nothing
7816 Statically linked - exit and init driver, as in rmmod and insmod
7817
Jeff Johnson76052702013-04-16 13:55:05 -07007818 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007819
Jeff Johnson76052702013-04-16 13:55:05 -07007820 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007821
7822 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07007823static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007824{
Jeff Johnson76052702013-04-16 13:55:05 -07007825 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007826
Jeff Johnson76052702013-04-16 13:55:05 -07007827 ret = param_set_int(kmessage, kp);
7828 if (0 == ret)
7829 ret = kickstart_driver();
7830 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007831}
7832#endif /* #ifdef MODULE */
7833
7834/**---------------------------------------------------------------------------
7835
Jeff Johnson295189b2012-06-20 16:38:30 -07007836 \brief hdd_get_conparam() -
7837
7838 This is the driver exit point (invoked when module is unloaded using rmmod)
7839
7840 \param - None
7841
7842 \return - tVOS_CON_MODE
7843
7844 --------------------------------------------------------------------------*/
7845tVOS_CON_MODE hdd_get_conparam ( void )
7846{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007847#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07007848 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007849#else
7850 return (tVOS_CON_MODE)curr_con_mode;
7851#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007852}
7853void hdd_set_conparam ( v_UINT_t newParam )
7854{
7855 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007856#ifndef MODULE
7857 curr_con_mode = con_mode;
7858#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007859}
7860/**---------------------------------------------------------------------------
7861
7862 \brief hdd_softap_sta_deauth() - function
7863
7864 This to take counter measure to handle deauth req from HDD
7865
7866 \param - pAdapter - Pointer to the HDD
7867
7868 \param - enable - boolean value
7869
7870 \return - None
7871
7872 --------------------------------------------------------------------------*/
7873
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007874VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07007875{
Jeff Johnson295189b2012-06-20 16:38:30 -07007876 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007877 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07007878
7879 ENTER();
7880
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07007881 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
7882 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007883
7884 //Ignore request to deauth bcmc station
7885 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007886 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07007887
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007888 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07007889
7890 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08007891 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07007892}
7893
7894/**---------------------------------------------------------------------------
7895
7896 \brief hdd_softap_sta_disassoc() - function
7897
7898 This to take counter measure to handle deauth req from HDD
7899
7900 \param - pAdapter - Pointer to the HDD
7901
7902 \param - enable - boolean value
7903
7904 \return - None
7905
7906 --------------------------------------------------------------------------*/
7907
7908void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
7909{
7910 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
7911
7912 ENTER();
7913
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307914 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007915
7916 //Ignore request to disassoc bcmc station
7917 if( pDestMacAddress[0] & 0x1 )
7918 return;
7919
7920 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
7921}
7922
7923void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
7924{
7925 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
7926
7927 ENTER();
7928
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307929 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007930
7931 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
7932}
7933
Jeff Johnson295189b2012-06-20 16:38:30 -07007934/**---------------------------------------------------------------------------
7935 *
7936 * \brief hdd_get__concurrency_mode() -
7937 *
7938 *
7939 * \param - None
7940 *
7941 * \return - CONCURRENCY MODE
7942 *
7943 * --------------------------------------------------------------------------*/
7944tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
7945{
7946 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
7947 hdd_context_t *pHddCtx;
7948
7949 if (NULL != pVosContext)
7950 {
7951 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
7952 if (NULL != pHddCtx)
7953 {
7954 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
7955 }
7956 }
7957
7958 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007959 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007960 return VOS_STA;
7961}
7962
7963/* Decide whether to allow/not the apps power collapse.
7964 * Allow apps power collapse if we are in connected state.
7965 * if not, allow only if we are in IMPS */
7966v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
7967{
7968 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08007969 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08007970 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07007971 hdd_config_t *pConfig = pHddCtx->cfg_ini;
7972 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
7973 hdd_adapter_t *pAdapter = NULL;
7974 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08007975 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007976
Jeff Johnson295189b2012-06-20 16:38:30 -07007977 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7978 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007979
Yathish9f22e662012-12-10 14:21:35 -08007980 concurrent_state = hdd_get_concurrency_mode();
7981
7982#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7983 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
7984 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
7985 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
7986 return TRUE;
7987#endif
7988
Jeff Johnson295189b2012-06-20 16:38:30 -07007989 /*loop through all adapters. TBD fix for Concurrency */
7990 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
7991 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
7992 {
7993 pAdapter = pAdapterNode->pAdapter;
7994 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
7995 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
7996 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08007997 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07007998 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08007999 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008000 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8001 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008002 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008003 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008004 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8005 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008006 return FALSE;
8007 }
8008 }
8009 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8010 pAdapterNode = pNext;
8011 }
8012 return TRUE;
8013}
8014
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008015/* Decides whether to send suspend notification to Riva
8016 * if any adapter is in BMPS; then it is required */
8017v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8018{
8019 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8020 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8021
8022 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8023 {
8024 return TRUE;
8025 }
8026 return FALSE;
8027}
8028
Jeff Johnson295189b2012-06-20 16:38:30 -07008029void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8030{
8031 switch(mode)
8032 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008033 case VOS_STA_MODE:
8034 case VOS_P2P_CLIENT_MODE:
8035 case VOS_P2P_GO_MODE:
8036 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008037 pHddCtx->concurrency_mode |= (1 << mode);
8038 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008039 break;
8040 default:
8041 break;
8042
8043 }
8044 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8045 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8046}
8047
8048
8049void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8050{
8051 switch(mode)
8052 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008053 case VOS_STA_MODE:
8054 case VOS_P2P_CLIENT_MODE:
8055 case VOS_P2P_GO_MODE:
8056 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008057 pHddCtx->no_of_sessions[mode]--;
8058 if (!(pHddCtx->no_of_sessions[mode]))
8059 pHddCtx->concurrency_mode &= (~(1 << mode));
8060 break;
8061 default:
8062 break;
8063 }
8064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8065 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8066}
8067
Jeff Johnsone7245742012-09-05 17:12:55 -07008068/**---------------------------------------------------------------------------
8069 *
8070 * \brief wlan_hdd_restart_init
8071 *
8072 * This function initalizes restart timer/flag. An internal function.
8073 *
8074 * \param - pHddCtx
8075 *
8076 * \return - None
8077 *
8078 * --------------------------------------------------------------------------*/
8079
8080static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8081{
8082 /* Initialize */
8083 pHddCtx->hdd_restart_retries = 0;
8084 atomic_set(&pHddCtx->isRestartInProgress, 0);
8085 vos_timer_init(&pHddCtx->hdd_restart_timer,
8086 VOS_TIMER_TYPE_SW,
8087 wlan_hdd_restart_timer_cb,
8088 pHddCtx);
8089}
8090/**---------------------------------------------------------------------------
8091 *
8092 * \brief wlan_hdd_restart_deinit
8093 *
8094 * This function cleans up the resources used. An internal function.
8095 *
8096 * \param - pHddCtx
8097 *
8098 * \return - None
8099 *
8100 * --------------------------------------------------------------------------*/
8101
8102static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8103{
8104
8105 VOS_STATUS vos_status;
8106 /* Block any further calls */
8107 atomic_set(&pHddCtx->isRestartInProgress, 1);
8108 /* Cleanup */
8109 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8110 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008111 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008112 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8113 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008114 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008115
8116}
8117
8118/**---------------------------------------------------------------------------
8119 *
8120 * \brief wlan_hdd_framework_restart
8121 *
8122 * This function uses a cfg80211 API to start a framework initiated WLAN
8123 * driver module unload/load.
8124 *
8125 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8126 *
8127 *
8128 * \param - pHddCtx
8129 *
8130 * \return - VOS_STATUS_SUCCESS: Success
8131 * VOS_STATUS_E_EMPTY: Adapter is Empty
8132 * VOS_STATUS_E_NOMEM: No memory
8133
8134 * --------------------------------------------------------------------------*/
8135
8136static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8137{
8138 VOS_STATUS status = VOS_STATUS_SUCCESS;
8139 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008140 int len = (sizeof (struct ieee80211_mgmt));
8141 struct ieee80211_mgmt *mgmt = NULL;
8142
8143 /* Prepare the DEAUTH managment frame with reason code */
8144 mgmt = kzalloc(len, GFP_KERNEL);
8145 if(mgmt == NULL)
8146 {
8147 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8148 "%s: memory allocation failed (%d bytes)", __func__, len);
8149 return VOS_STATUS_E_NOMEM;
8150 }
8151 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008152
8153 /* Iterate over all adapters/devices */
8154 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8155 do
8156 {
8157 if( (status == VOS_STATUS_SUCCESS) &&
8158 pAdapterNode &&
8159 pAdapterNode->pAdapter)
8160 {
8161 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8162 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8163 pAdapterNode->pAdapter->dev->name,
8164 pAdapterNode->pAdapter->device_mode,
8165 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008166 /*
8167 * CFG80211 event to restart the driver
8168 *
8169 * 'cfg80211_send_unprot_deauth' sends a
8170 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8171 * of SME(Linux Kernel) state machine.
8172 *
8173 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8174 * the driver.
8175 *
8176 */
8177
8178 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008179 }
8180 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8181 pAdapterNode = pNext;
8182 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8183
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008184
8185 /* Free the allocated management frame */
8186 kfree(mgmt);
8187
Jeff Johnsone7245742012-09-05 17:12:55 -07008188 /* Retry until we unload or reach max count */
8189 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8190 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8191
8192 return status;
8193
8194}
8195/**---------------------------------------------------------------------------
8196 *
8197 * \brief wlan_hdd_restart_timer_cb
8198 *
8199 * Restart timer callback. An internal function.
8200 *
8201 * \param - User data:
8202 *
8203 * \return - None
8204 *
8205 * --------------------------------------------------------------------------*/
8206
8207void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8208{
8209 hdd_context_t *pHddCtx = usrDataForCallback;
8210 wlan_hdd_framework_restart(pHddCtx);
8211 return;
8212
8213}
8214
8215
8216/**---------------------------------------------------------------------------
8217 *
8218 * \brief wlan_hdd_restart_driver
8219 *
8220 * This function sends an event to supplicant to restart the WLAN driver.
8221 *
8222 * This function is called from vos_wlanRestart.
8223 *
8224 * \param - pHddCtx
8225 *
8226 * \return - VOS_STATUS_SUCCESS: Success
8227 * VOS_STATUS_E_EMPTY: Adapter is Empty
8228 * VOS_STATUS_E_ALREADY: Request already in progress
8229
8230 * --------------------------------------------------------------------------*/
8231VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8232{
8233 VOS_STATUS status = VOS_STATUS_SUCCESS;
8234
8235 /* A tight check to make sure reentrancy */
8236 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8237 {
8238 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8239 "%s: WLAN restart is already in progress", __func__);
8240
8241 return VOS_STATUS_E_ALREADY;
8242 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008243 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008244#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008245 wcnss_reset_intr();
8246#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008247
Jeff Johnsone7245742012-09-05 17:12:55 -07008248 return status;
8249}
8250
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008251/*
8252 * API to find if there is any STA or P2P-Client is connected
8253 */
8254VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8255{
8256 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8257}
Jeff Johnsone7245742012-09-05 17:12:55 -07008258
Jeff Johnson295189b2012-06-20 16:38:30 -07008259//Register the module init/exit functions
8260module_init(hdd_module_init);
8261module_exit(hdd_module_exit);
8262
8263MODULE_LICENSE("Dual BSD/GPL");
8264MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8265MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8266
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008267module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8268 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008269
Jeff Johnson76052702013-04-16 13:55:05 -07008270module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07008271 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);