blob: 5a6e8cbb93e9f365a1d6fe9fdd319be1c0cccf6c [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
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700172#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
173#define TID_MIN_VALUE 0
174#define TID_MAX_VALUE 15
175static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
176 tAniTrafStrmMetrics* pTsmMetrics);
177#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
178
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700179/*
180 * Driver miracast parameters 0-Disabled
181 * 1-Source, 2-Sink
182 */
183#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
184#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
185
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800186#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700187static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700188#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700189/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700190static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700191
192//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700193static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
194static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
195static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
196void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800197void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700198
Jeff Johnson295189b2012-06-20 16:38:30 -0700199v_U16_t hdd_select_queue(struct net_device *dev,
200 struct sk_buff *skb);
201
202#ifdef WLAN_FEATURE_PACKET_FILTERING
203static void hdd_set_multicast_list(struct net_device *dev);
204#endif
205
206void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700207int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700208
209extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800210#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
211void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
212static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700213static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
214 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
215 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700216static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
217 tANI_U8 *pTargetApBssid,
218 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800219#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700220#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
221VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
222#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
223
Jeff Johnson295189b2012-06-20 16:38:30 -0700224static int hdd_netdev_notifier_call(struct notifier_block * nb,
225 unsigned long state,
226 void *ndev)
227{
228 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700229 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700230 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700231#ifdef WLAN_BTAMP_FEATURE
232 VOS_STATUS status;
233 hdd_context_t *pHddCtx;
234#endif
235
236 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700237 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700238 (strncmp(dev->name, "p2p", 3)))
239 return NOTIFY_DONE;
240
241 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700242 return NOTIFY_DONE;
243
Jeff Johnson295189b2012-06-20 16:38:30 -0700244 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700245 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700246
Jeff Johnson27cee452013-03-27 11:10:24 -0700247 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700248 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800249 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700250 VOS_ASSERT(0);
251 return NOTIFY_DONE;
252 }
253
Jeff Johnson27cee452013-03-27 11:10:24 -0700254 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
255 if (NULL == pHddCtx)
256 {
257 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
258 VOS_ASSERT(0);
259 return NOTIFY_DONE;
260 }
261
262 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
263 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700264
265 switch (state) {
266 case NETDEV_REGISTER:
267 break;
268
269 case NETDEV_UNREGISTER:
270 break;
271
272 case NETDEV_UP:
273 break;
274
275 case NETDEV_DOWN:
276 break;
277
278 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700279 if(TRUE == pAdapter->isLinkUpSvcNeeded)
280 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700281 break;
282
283 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700284 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700285 {
286 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800287 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530288 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700289 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800290 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700291 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
292 if(!result)
293 {
294 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800295 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700296 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700297 }
298 }
299 else
300 {
301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700302 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700303 }
304#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700305 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700306 status = WLANBAP_StopAmp();
307 if(VOS_STATUS_SUCCESS != status )
308 {
309 pHddCtx->isAmpAllowed = VOS_TRUE;
310 hddLog(VOS_TRACE_LEVEL_FATAL,
311 "%s: Failed to stop AMP", __func__);
312 }
313 else
314 {
315 //a state m/c implementation in PAL is TBD to avoid this delay
316 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700317 if ( pHddCtx->isAmpAllowed )
318 {
319 WLANBAP_DeregisterFromHCI();
320 pHddCtx->isAmpAllowed = VOS_FALSE;
321 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700322 }
323#endif //WLAN_BTAMP_FEATURE
324 break;
325
326 default:
327 break;
328 }
329
330 return NOTIFY_DONE;
331}
332
333struct notifier_block hdd_netdev_notifier = {
334 .notifier_call = hdd_netdev_notifier_call,
335};
336
337/*---------------------------------------------------------------------------
338 * Function definitions
339 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700340void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
341void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700342//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700343static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700344#ifndef MODULE
345/* current con_mode - used only for statically linked driver
346 * con_mode is changed by userspace to indicate a mode change which will
347 * result in calling the module exit and init functions. The module
348 * exit function will clean up based on the value of con_mode prior to it
349 * being changed by userspace. So curr_con_mode records the current con_mode
350 * for exit when con_mode becomes the next mode for init
351 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700352static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700353#endif
354
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800355/**---------------------------------------------------------------------------
356
357 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
358
359 Called immediately after the cfg.ini is read in order to configure
360 the desired trace levels.
361
362 \param - moduleId - module whose trace level is being configured
363 \param - bitmask - bitmask of log levels to be enabled
364
365 \return - void
366
367 --------------------------------------------------------------------------*/
368static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
369{
370 wpt_tracelevel level;
371
372 /* if the bitmask is the default value, then a bitmask was not
373 specified in cfg.ini, so leave the logging level alone (it
374 will remain at the "compiled in" default value) */
375 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
376 {
377 return;
378 }
379
380 /* a mask was specified. start by disabling all logging */
381 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
382
383 /* now cycle through the bitmask until all "set" bits are serviced */
384 level = VOS_TRACE_LEVEL_FATAL;
385 while (0 != bitmask)
386 {
387 if (bitmask & 1)
388 {
389 vos_trace_setValue(moduleId, level, 1);
390 }
391 level++;
392 bitmask >>= 1;
393 }
394}
395
396
Jeff Johnson295189b2012-06-20 16:38:30 -0700397/**---------------------------------------------------------------------------
398
399 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
400
401 Called immediately after the cfg.ini is read in order to configure
402 the desired trace levels in the WDI.
403
404 \param - moduleId - module whose trace level is being configured
405 \param - bitmask - bitmask of log levels to be enabled
406
407 \return - void
408
409 --------------------------------------------------------------------------*/
410static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
411{
412 wpt_tracelevel level;
413
414 /* if the bitmask is the default value, then a bitmask was not
415 specified in cfg.ini, so leave the logging level alone (it
416 will remain at the "compiled in" default value) */
417 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
418 {
419 return;
420 }
421
422 /* a mask was specified. start by disabling all logging */
423 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
424
425 /* now cycle through the bitmask until all "set" bits are serviced */
426 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
427 while (0 != bitmask)
428 {
429 if (bitmask & 1)
430 {
431 wpalTraceSetLevel(moduleId, level, 1);
432 }
433 level++;
434 bitmask >>= 1;
435 }
436}
Jeff Johnson295189b2012-06-20 16:38:30 -0700437
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530438/*
439 * FUNCTION: wlan_hdd_validate_context
440 * This function is used to check the HDD context
441 */
442int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
443{
444 ENTER();
445
446 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
447 {
448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
449 "%s: HDD context is Null", __func__);
450 return -ENODEV;
451 }
452
453 if (pHddCtx->isLogpInProgress)
454 {
455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
456 "%s: LOGP in Progress. Ignore!!!", __func__);
457 return -EAGAIN;
458 }
459
460 if (pHddCtx->isLoadUnloadInProgress)
461 {
462 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
463 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
464 return -EAGAIN;
465 }
466 return 0;
467}
468
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530469void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
470{
471 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
472 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
473 hdd_config_t *cfg_param;
474 eCsrPhyMode phyMode;
475
476 if (NULL == pHddCtx)
477 {
478 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
479 "HDD Context is null !!");
480 return ;
481 }
482
483 cfg_param = pHddCtx->cfg_ini;
484
485 if (NULL == cfg_param)
486 {
487 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
488 "cfg_params not available !!");
489 return ;
490 }
491
492 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
493
494 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
495 {
496 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
497 (eCSR_DOT11_MODE_11ac == phyMode) ||
498 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
499 {
500 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
501 "Setting phymode to 11n!!");
502 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
503 }
504 }
505 else
506 {
507 /*New country Supports 11ac as well resetting value back from .ini*/
508 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
509 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
510 return ;
511 }
512
513 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
514 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
515 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
516 {
517 VOS_STATUS vosStatus;
518
519 // need to issue a disconnect to CSR.
520 INIT_COMPLETION(pAdapter->disconnect_comp_var);
521 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
522 pAdapter->sessionId,
523 eCSR_DISCONNECT_REASON_UNSPECIFIED );
524
525 if (VOS_STATUS_SUCCESS == vosStatus)
526 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
527 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
528
529 }
530}
531
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700532void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
533{
534 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
535 hdd_config_t *cfg_param;
536
537 if (NULL == pHddCtx)
538 {
539 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
540 "HDD Context is null !!");
541 return ;
542 }
543
544 cfg_param = pHddCtx->cfg_ini;
545
546 if (NULL == cfg_param)
547 {
548 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
549 "cfg_params not available !!");
550 return ;
551 }
552
553 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
554 {
555 /*New country doesn't support DFS */
556 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
557 }
558 else
559 {
560 /*New country Supports DFS as well resetting value back from .ini*/
561 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
562 }
563
564}
565
Rajeev79dbe4c2013-10-05 11:03:42 +0530566#ifdef FEATURE_WLAN_BATCH_SCAN
567
568/**---------------------------------------------------------------------------
569
570 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
571 input string
572
573 This function extracts assigned integer from string in below format:
574 "STRING=10" : extracts integer 10 from this string
575
576 \param - pInPtr Pointer to input string
577 \param - base Base for string to int conversion(10 for decimal 16 for hex)
578 \param - pOutPtr Pointer to variable in which extracted integer needs to be
579 assigned
580 \param - pLastArg to tell whether it is last arguement in input string or
581 not
582
583 \return - NULL for failure cases
584 pointer to next arguement in input string for success cases
585 --------------------------------------------------------------------------*/
586static tANI_U8 *
587hdd_extract_assigned_int_from_str
588(
589 tANI_U8 *pInPtr,
590 tANI_U8 base,
591 tANI_U32 *pOutPtr,
592 tANI_U8 *pLastArg
593)
594{
595 int tempInt;
596 int v = 0;
597 char buf[32];
598 int val = 0;
599 *pLastArg = FALSE;
600
601 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
602 if (NULL == pInPtr)
603 {
604 return NULL;
605 }
606
607 pInPtr++;
608
609 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
610
611 val = sscanf(pInPtr, "%32s ", buf);
612 if (val < 0 && val > strlen(pInPtr))
613 {
614 return NULL;
615 }
616 pInPtr += val;
617 v = kstrtos32(buf, base, &tempInt);
618 if (v < 0)
619 {
620 return NULL;
621 }
622 *pOutPtr = tempInt;
623
624 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
625 if (NULL == pInPtr)
626 {
627 *pLastArg = TRUE;
628 return NULL;
629 }
630 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
631
632 return pInPtr;
633}
634
635/**---------------------------------------------------------------------------
636
637 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
638 input string
639
640 This function extracts assigned character from string in below format:
641 "STRING=A" : extracts char 'A' from this string
642
643 \param - pInPtr Pointer to input string
644 \param - pOutPtr Pointer to variable in which extracted char needs to be
645 assigned
646 \param - pLastArg to tell whether it is last arguement in input string or
647 not
648
649 \return - NULL for failure cases
650 pointer to next arguement in input string for success cases
651 --------------------------------------------------------------------------*/
652static tANI_U8 *
653hdd_extract_assigned_char_from_str
654(
655 tANI_U8 *pInPtr,
656 tANI_U8 *pOutPtr,
657 tANI_U8 *pLastArg
658)
659{
660 *pLastArg = FALSE;
661
662 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
663 if (NULL == pInPtr)
664 {
665 return NULL;
666 }
667
668 pInPtr++;
669
670 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
671
672 *pOutPtr = *pInPtr;
673
674 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
675 if (NULL == pInPtr)
676 {
677 *pLastArg = TRUE;
678 return NULL;
679 }
680 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
681
682 return pInPtr;
683}
684
685
686/**---------------------------------------------------------------------------
687
688 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
689
690 This function parses set batch scan command in below format:
691 WLS_BATCHING_SET <space> followed by below arguements
692 "SCANFREQ=XX" : Optional defaults to 30 sec
693 "MSCAN=XX" : Required number of scans to attempt to batch
694 "BESTN=XX" : Best Network (RSSI) defaults to 16
695 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
696 A. implies only 5 GHz , B. implies only 2.4GHz
697 "RTT=X" : optional defaults to 0
698 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
699 error
700
701 For example input commands:
702 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
703 translated into set batch scan with following parameters:
704 a) Frequence 60 seconds
705 b) Batch 10 scans together
706 c) Best RSSI to be 20
707 d) 5GHz band only
708 e) RTT is equal to 0
709
710 \param - pValue Pointer to input channel list
711 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
712
713 \return - 0 for success non-zero for failure
714
715 --------------------------------------------------------------------------*/
716static int
717hdd_parse_set_batchscan_command
718(
719 tANI_U8 *pValue,
720 tSirSetBatchScanReq *pHddSetBatchScanReq
721)
722{
723 tANI_U8 *inPtr = pValue;
724 tANI_U8 val = 0;
725 tANI_U8 lastArg = 0;
726
727 /*initialize default values*/
728 pHddSetBatchScanReq->scanFrequency = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
729 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
730 pHddSetBatchScanReq->rtt = 0;
731 pHddSetBatchScanReq->bestNetwork = HDD_SET_BATCH_SCAN_BEST_NETWORK;
732
733 /*go to space after WLS_BATCHING_SET command*/
734 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
735 /*no argument after the command*/
736 if (NULL == inPtr)
737 {
738 return -EINVAL;
739 }
740
741 /*no space after the command*/
742 else if (SPACE_ASCII_VALUE != *inPtr)
743 {
744 return -EINVAL;
745 }
746
747 /*removing empty spaces*/
748 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
749
750 /*no argument followed by spaces*/
751 if ('\0' == *inPtr)
752 {
753 return -EINVAL;
754 }
755
756 /*check and parse SCANFREQ*/
757 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
758 {
759 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
760 &pHddSetBatchScanReq->scanFrequency, &lastArg);
761 if ( (NULL == inPtr) || (TRUE == lastArg))
762 {
763 return -EINVAL;
764 }
765 }
766
767 /*check and parse MSCAN*/
768 if ((strncmp(inPtr, "MSCAN", 5) == 0))
769 {
770 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
771 &pHddSetBatchScanReq->numberOfScansToBatch, &lastArg);
772 if (TRUE == lastArg)
773 {
774 goto done;
775 }
776 else if (NULL == inPtr)
777 {
778 return -EINVAL;
779 }
780 }
781 else
782 {
783 return -EINVAL;
784 }
785
786 /*check and parse BESTN*/
787 if ((strncmp(inPtr, "BESTN", 5) == 0))
788 {
789 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
790 &pHddSetBatchScanReq->bestNetwork, &lastArg);
791 if (TRUE == lastArg)
792 {
793 goto done;
794 }
795 else if (NULL == inPtr)
796 {
797 return -EINVAL;
798 }
799 }
800
801 /*check and parse CHANNEL*/
802 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
803 {
804 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
805 if (TRUE == lastArg)
806 {
807 goto done;
808 }
809 else if (NULL == inPtr)
810 {
811 return -EINVAL;
812 }
813 if (('A' == val) || ('a' == val))
814 {
815 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
816 }
817 else if (('B' == val) || ('b' == val))
818 {
819 pHddSetBatchScanReq->rfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
820 }
821 else
822 {
823 return -EINVAL;
824 }
825 }
826
827 /*check and parse RTT*/
828 if ((strncmp(inPtr, "RTT", 3) == 0))
829 {
830 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
831 &pHddSetBatchScanReq->rtt, &lastArg);
832 if (TRUE == lastArg)
833 {
834 goto done;
835 }
836 if (NULL == inPtr)
837 {
838 return -EINVAL;
839 }
840 }
841
842
843done:
844
845 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
846 "Received WLS_BATCHING_SET with SCANFREQ=%d "
847 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
848 pHddSetBatchScanReq->scanFrequency,
849 pHddSetBatchScanReq->numberOfScansToBatch,
850 pHddSetBatchScanReq->bestNetwork,
851 pHddSetBatchScanReq->rfBand,
852 pHddSetBatchScanReq->rtt);
853
854 return 0;
855}/*End of hdd_parse_set_batchscan_command*/
856
857/**---------------------------------------------------------------------------
858
859 \brief hdd_set_batch_scan_req_callback () - This function is called after
860 receiving set batch scan response from FW and it saves set batch scan
861 response data FW to HDD context and sets the completion event on
862 which hdd_ioctl is waiting
863
864 \param - callbackContext Pointer to HDD adapter
865 \param - pRsp Pointer to set batch scan response data received from FW
866
867 \return - nothing
868
869 --------------------------------------------------------------------------*/
870static void hdd_set_batch_scan_req_callback
871(
872 void *callbackContext,
873 tSirSetBatchScanRsp *pRsp
874)
875{
876 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
877 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
878
879 /*sanity check*/
880 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
881 {
882 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
883 "%s: Invalid pAdapter magic", __func__);
884 VOS_ASSERT(0);
885 return;
886 }
887 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
888
889 /*save set batch scan response*/
890 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
891
892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
893 "Received set batch scan rsp from FW with nScansToBatch=%d",
894 pHddSetBatchScanRsp->nScansToBatch);
895
896 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
897 complete(&pAdapter->hdd_set_batch_scan_req_var);
898
899 return;
900}/*End of hdd_set_batch_scan_req_callback*/
901
902
903/**---------------------------------------------------------------------------
904
905 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
906 info in hdd batch scan response queue
907
908 \param - pAdapter Pointer to hdd adapter
909 \param - pAPMetaInfo Pointer to access point meta info
910 \param - scanId scan ID of batch scan response
911 \param - isLastAp tells whether AP is last AP in batch scan response or not
912
913 \return - nothing
914
915 --------------------------------------------------------------------------*/
916static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
917 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
918{
919 tHddBatchScanRsp *pHead;
920 tHddBatchScanRsp *pNode;
921 tHddBatchScanRsp *pPrev;
922 tHddBatchScanRsp *pTemp;
923 tANI_U8 ssidLen;
924
925 /*head of hdd batch scan response queue*/
926 pHead = pAdapter->pBatchScanRsp;
927
928 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
929 if (NULL == pNode)
930 {
931 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
932 "%s: Could not allocate memory", __func__);
933 VOS_ASSERT(0);
934 return;
935 }
936
937 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
938 sizeof(pNode->ApInfo.bssid));
939 ssidLen = strlen(pApMetaInfo->ssid);
940 if (SIR_MAX_SSID_SIZE < ssidLen)
941 {
942 /*invalid scan result*/
943 vos_mem_free(pNode);
944 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
945 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
946 return;
947 }
948 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
949 /*null terminate ssid*/
950 pNode->ApInfo.ssid[ssidLen] = '\0';
951 pNode->ApInfo.ch = pApMetaInfo->ch;
952 pNode->ApInfo.rssi = pApMetaInfo->rssi;
953 pNode->ApInfo.age = pApMetaInfo->timestamp;
954 pNode->ApInfo.batchId = scanId;
955 pNode->ApInfo.isLastAp = isLastAp;
956
957 pNode->pNext = NULL;
958 if (NULL == pHead)
959 {
960 pAdapter->pBatchScanRsp = pNode;
961 }
962 else
963 {
964 pTemp = pHead;
965 while (NULL != pTemp)
966 {
967 pPrev = pTemp;
968 pTemp = pTemp->pNext;
969 }
970 pPrev->pNext = pNode;
971 }
972
973 return;
974}/*End of hdd_populate_batch_scan_rsp_queue*/
975
976/**---------------------------------------------------------------------------
977
978 \brief hdd_batch_scan_result_ind_callback () - This function is called after
979 receiving batch scan response indication from FW. It saves get batch scan
980 response data in HDD batch scan response queue. This callback sets the
981 completion event on which hdd_ioctl is waiting only after getting complete
982 batch scan response data from FW
983
984 \param - callbackContext Pointer to HDD adapter
985 \param - pRsp Pointer to get batch scan response data received from FW
986
987 \return - nothing
988
989 --------------------------------------------------------------------------*/
990static void hdd_batch_scan_result_ind_callback
991(
992 void *callbackContext,
993 void *pRsp
994)
995{
996 v_BOOL_t isLastAp;
997 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -0700998 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +0530999 tANI_U32 numberScanList;
1000 tANI_U32 nextScanListOffset;
1001 tANI_U32 nextApMetaInfoOffset;
1002 hdd_adapter_t* pAdapter;
1003 tpSirBatchScanList pScanList;
1004 tpSirBatchScanNetworkInfo pApMetaInfo;
1005 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1006 tSirSetBatchScanReq *pReq;
1007
1008 pAdapter = (hdd_adapter_t *)callbackContext;
1009 /*sanity check*/
1010 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1011 {
1012 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1013 "%s: Invalid pAdapter magic", __func__);
1014 VOS_ASSERT(0);
1015 return;
1016 }
1017
1018 /*initialize locals*/
1019 pReq = &pAdapter->hddSetBatchScanReq;
1020 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1021 isLastAp = FALSE;
1022 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001023 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301024 numberScanList = 0;
1025 nextScanListOffset = 0;
1026 nextApMetaInfoOffset = 0;
1027 pScanList = NULL;
1028 pApMetaInfo = NULL;
1029
1030 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1031 {
1032 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1033 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1034 isLastAp = TRUE;
1035 goto done;
1036 }
1037
1038 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1039 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1040 "Batch scan rsp: numberScalList %d", numberScanList);
1041
1042 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1043 {
1044 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1045 "%s: numberScanList %d", __func__, numberScanList);
1046 isLastAp = TRUE;
1047 goto done;
1048 }
1049
1050 while (numberScanList)
1051 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001052 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301053 nextScanListOffset);
1054 if (NULL == pScanList)
1055 {
1056 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1057 "%s: pScanList is %p", __func__, pScanList);
1058 isLastAp = TRUE;
1059 goto done;
1060 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001061 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301062 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001063 "Batch scan rsp: numApMetaInfo %d scanId %d",
1064 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301065
1066 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1067 {
1068 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1069 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1070 isLastAp = TRUE;
1071 goto done;
1072 }
1073
Rajeev Kumarce651e42013-10-21 18:57:15 -07001074 /*Initialize next AP meta info offset for next scan list*/
1075 nextApMetaInfoOffset = 0;
1076
Rajeev79dbe4c2013-10-05 11:03:42 +05301077 while (numApMetaInfo)
1078 {
1079 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1080 nextApMetaInfoOffset);
1081 if (NULL == pApMetaInfo)
1082 {
1083 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1084 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1085 isLastAp = TRUE;
1086 goto done;
1087 }
1088 /*calculate AP age*/
1089 pApMetaInfo->timestamp =
1090 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1091
1092 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1093 "%s: bssId 0x%x:0x%x:0x%x:0x%x:0x%x:0x%x "
1094 "ch %d rssi %d timestamp %d", __func__,
1095 pApMetaInfo->bssid[0],pApMetaInfo->bssid[1],
1096 pApMetaInfo->bssid[2],pApMetaInfo->bssid[3],
1097 pApMetaInfo->bssid[4],pApMetaInfo->bssid[5],
1098 pApMetaInfo->ch, pApMetaInfo->rssi,
1099 pApMetaInfo->timestamp);
1100
1101 /*mark last AP in batch scan response*/
1102 if ((TRUE == pBatchScanRsp->isLastResult) &&
1103 (1 == numberScanList) && (1 == numApMetaInfo))
1104 {
1105 isLastAp = TRUE;
1106 }
1107
1108 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1109 /*store batch scan repsonse in hdd queue*/
1110 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1111 pScanList->scanId, isLastAp);
1112 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1113
1114 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1115 numApMetaInfo--;
1116 }
1117
Rajeev Kumarce651e42013-10-21 18:57:15 -07001118 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1119 + (sizeof(tSirBatchScanNetworkInfo)
1120 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301121 numberScanList--;
1122 }
1123
1124done:
1125
1126 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1127 requested from hdd_ioctl*/
1128 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1129 (TRUE == isLastAp))
1130 {
1131 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1132 complete(&pAdapter->hdd_get_batch_scan_req_var);
1133 }
1134
1135 return;
1136}/*End of hdd_batch_scan_result_ind_callback*/
1137
1138/**---------------------------------------------------------------------------
1139
1140 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1141 response as per batch scan FR request format by putting proper markers
1142
1143 \param - pDest pointer to destination buffer
1144 \param - cur_len current length
1145 \param - tot_len total remaining size which can be written to user space
1146 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1147 \param - pAdapter Pointer to HDD adapter
1148
1149 \return - ret no of characters written
1150
1151 --------------------------------------------------------------------------*/
1152static tANI_U32
1153hdd_format_batch_scan_rsp
1154(
1155 tANI_U8 *pDest,
1156 tANI_U32 cur_len,
1157 tANI_U32 tot_len,
1158 tHddBatchScanRsp *pApMetaInfo,
1159 hdd_adapter_t* pAdapter
1160)
1161{
1162 tANI_U32 ret = 0;
1163 tANI_U32 rem_len = 0;
1164 tANI_U8 temp_len = 0;
1165 tANI_U8 temp_total_len = 0;
1166 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1167 tANI_U8 *pTemp = temp;
1168
1169 /*Batch scan reponse needs to be returned to user space in
1170 following format:
1171 "scancount=X\n" where X is the number of scans in current batch
1172 batch
1173 "trunc\n" optional present if current scan truncated
1174 "bssid=XX:XX:XX:XX:XX:XX\n"
1175 "ssid=XXXX\n"
1176 "freq=X\n" frequency in Mhz
1177 "level=XX\n"
1178 "age=X\n" ms
1179 "dist=X\n" cm (-1 if not available)
1180 "errror=X\n" (-1if not available)
1181 "====\n" (end of ap marker)
1182 "####\n" (end of scan marker)
1183 "----\n" (end of results)*/
1184 /*send scan result in above format to user space based on
1185 available length*/
1186 /*The GET response may have more data than the driver can return in its
1187 buffer. In that case the buffer should be filled to the nearest complete
1188 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1189 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1190 The final buffer should end with "----\n"*/
1191
1192 /*sanity*/
1193 if (cur_len > tot_len)
1194 {
1195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1196 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1197 return 0;
1198 }
1199 else
1200 {
1201 rem_len = (tot_len - cur_len);
1202 }
1203
1204 /*end scan marker*/
1205 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1206 {
1207 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1208 pTemp += temp_len;
1209 temp_total_len += temp_len;
1210 }
1211
1212 /*bssid*/
1213 temp_len = snprintf(pTemp, sizeof(temp),
1214 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1215 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1216 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1217 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1218 pTemp += temp_len;
1219 temp_total_len += temp_len;
1220
1221 /*ssid*/
1222 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1223 pApMetaInfo->ApInfo.ssid);
1224 pTemp += temp_len;
1225 temp_total_len += temp_len;
1226
1227 /*freq*/
1228 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
1229 pApMetaInfo->ApInfo.ch);
1230 pTemp += temp_len;
1231 temp_total_len += temp_len;
1232
1233 /*level*/
1234 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1235 pApMetaInfo->ApInfo.rssi);
1236 pTemp += temp_len;
1237 temp_total_len += temp_len;
1238
1239 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001240 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301241 pApMetaInfo->ApInfo.age);
1242 pTemp += temp_len;
1243 temp_total_len += temp_len;
1244
1245 /*dist*/
1246 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1247 pTemp += temp_len;
1248 temp_total_len += temp_len;
1249
1250 /*error*/
1251 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1252 pTemp += temp_len;
1253 temp_total_len += temp_len;
1254
1255 /*end AP marker*/
1256 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1257 pTemp += temp_len;
1258 temp_total_len += temp_len;
1259
1260 /*last AP in batch scan response*/
1261 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1262 {
1263 /*end scan marker*/
1264 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1265 pTemp += temp_len;
1266 temp_total_len += temp_len;
1267
1268 /*end batch scan result marker*/
1269 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1270 pTemp += temp_len;
1271 temp_total_len += temp_len;
1272 }
1273
1274 if (temp_total_len < rem_len)
1275 {
1276 ret = temp_total_len + 1;
1277 strlcpy(pDest, temp, ret);
1278 pAdapter->isTruncated = FALSE;
1279 }
1280 else
1281 {
1282 pAdapter->isTruncated = TRUE;
1283 if (rem_len >= strlen("%%%%"))
1284 {
1285 ret = snprintf(pDest, strlen("%%%%"), "%%%%");
1286 }
1287 {
1288 ret = 0;
1289 }
1290 }
1291
1292 return ret;
1293
1294}/*End of hdd_format_batch_scan_rsp*/
1295
1296/**---------------------------------------------------------------------------
1297
1298 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1299 buffer starting with head of hdd batch scan response queue
1300
1301 \param - pAdapter Pointer to HDD adapter
1302 \param - pDest Pointer to user data buffer
1303 \param - cur_len current offset in user buffer
1304 \param - rem_len remaining no of bytes in user buffer
1305
1306 \return - number of bytes written in user buffer
1307
1308 --------------------------------------------------------------------------*/
1309
1310tANI_U32 hdd_populate_user_batch_scan_rsp
1311(
1312 hdd_adapter_t* pAdapter,
1313 tANI_U8 *pDest,
1314 tANI_U32 cur_len,
1315 tANI_U32 rem_len
1316)
1317{
1318 tHddBatchScanRsp *pHead;
1319 tHddBatchScanRsp *pPrev;
1320 tANI_U32 len;
1321
1322 pAdapter->prev_batch_id = 0;
1323 pAdapter->isTruncated = FALSE;
1324
1325 /*head of hdd batch scan response queue*/
1326 pHead = pAdapter->pBatchScanRsp;
1327 while (pHead)
1328 {
1329 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1330 pAdapter);
1331 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001332 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301333 cur_len += len;
1334 if(TRUE == pAdapter->isTruncated)
1335 {
1336 /*result is truncated return rest of scan rsp in next req*/
1337 cur_len = rem_len;
1338 break;
1339 }
1340 pPrev = pHead;
1341 pHead = pHead->pNext;
1342 pAdapter->pBatchScanRsp = pHead;
1343 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1344 vos_mem_free(pPrev);
1345 }
1346
1347 return cur_len;
1348}/*End of hdd_populate_user_batch_scan_rsp*/
1349
1350/**---------------------------------------------------------------------------
1351
1352 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1353 scan response data from HDD queue to user space
1354 It does following in detail:
1355 a) if HDD has enough data in its queue then it 1st copies data to user
1356 space and then send get batch scan indication message to FW. In this
1357 case it does not wait on any event and batch scan response data will
1358 be populated in HDD response queue in MC thread context after receiving
1359 indication from FW
1360 b) else send get batch scan indication message to FW and wait on an event
1361 which will be set once HDD receives complete batch scan response from
1362 FW and then this function returns batch scan response to user space
1363
1364 \param - pAdapter Pointer to HDD adapter
1365 \param - pPrivData Pointer to priv_data
1366
1367 \return - 0 for success -EFAULT for failure
1368
1369 --------------------------------------------------------------------------*/
1370
1371int hdd_return_batch_scan_rsp_to_user
1372(
1373 hdd_adapter_t* pAdapter,
1374 hdd_priv_data_t *pPrivData,
1375 tANI_U8 *command
1376)
1377{
1378 tANI_U8 *pDest;
1379 tANI_U32 count = 0;
1380 tANI_U32 len = 0;
1381 tANI_U32 cur_len = 0;
1382 tANI_U32 rem_len = 0;
1383 eHalStatus halStatus;
1384 unsigned long rc;
1385 tSirTriggerBatchScanResultInd *pReq;
1386
1387 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1388 pReq->param = 0;/*batch scan client*/
1389 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1390 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1391
1392 cur_len = pPrivData->used_len;
1393 if (pPrivData->total_len > pPrivData->used_len)
1394 {
1395 rem_len = pPrivData->total_len - pPrivData->used_len;
1396 }
1397 else
1398 {
1399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1400 "%s: Invalid user data buffer total_len %d used_len %d",
1401 __func__, pPrivData->total_len, pPrivData->used_len);
1402 return -EFAULT;
1403 }
1404
1405 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1406 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1407 cur_len, rem_len);
1408 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1409
1410 /*enough scan result available in cache to return to user space or
1411 scan result needs to be fetched 1st from fw and then return*/
1412 if (len < rem_len)
1413 {
1414 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1415 halStatus = sme_TriggerBatchScanResultInd(
1416 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1417 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1418 pAdapter);
1419 if ( eHAL_STATUS_SUCCESS == halStatus )
1420 {
1421 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1422 {
1423 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1424 rc = wait_for_completion_timeout(
1425 &pAdapter->hdd_get_batch_scan_req_var,
1426 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1427 if (0 == rc)
1428 {
1429 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1430 "%s: Timeout waiting to fetch batch scan rsp from fw",
1431 __func__);
1432 return -EFAULT;
1433 }
1434 }
1435
1436 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001437 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301438 pDest += len;
1439 cur_len += len;
1440
1441 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1442 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1443 cur_len, rem_len);
1444 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1445
1446 count = 0;
1447 len = (len - pPrivData->used_len);
1448 pDest = (command + pPrivData->used_len);
1449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1450 "BATCH SCAN RESULT:");
1451 while(count < len)
1452 {
1453 printk("%c", *(pDest + count));
1454 count++;
1455 }
1456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1457 "%s: copy %d data to user buffer", __func__, len);
1458 if (copy_to_user(pPrivData->buf, pDest, len))
1459 {
1460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1461 "%s: failed to copy data to user buffer", __func__);
1462 return -EFAULT;
1463 }
1464 }
1465 else
1466 {
1467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1468 "sme_GetBatchScanScan returned failure halStatus %d",
1469 halStatus);
1470 return -EINVAL;
1471 }
1472 }
1473 else
1474 {
1475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1476 "%s: copy %d data to user buffer", __func__, len);
1477 count = 0;
1478 len = (len - pPrivData->used_len);
1479 pDest = (command + pPrivData->used_len);
1480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1481 "BATCH SCAN RESULT:");
1482 while(count < len)
1483 {
1484 printk("%c", *(pDest + count));
1485 count++;
1486 }
1487 if (copy_to_user(pPrivData->buf, pDest, len))
1488 {
1489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1490 "%s: failed to copy data to user buffer", __func__);
1491 return -EFAULT;
1492 }
1493 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1494 halStatus = sme_TriggerBatchScanResultInd(
1495 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1496 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1497 pAdapter);
1498 if ( eHAL_STATUS_SUCCESS != halStatus )
1499 {
1500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1501 "sme_GetBatchScanScan returned failure halStatus %d",
1502 halStatus);
1503 }
1504 }
1505
1506 return 0;
1507} /*End of hdd_return_batch_scan_rsp_to_user*/
1508
1509#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1510
Jeff Johnson295189b2012-06-20 16:38:30 -07001511int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1512{
1513 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1514 hdd_priv_data_t priv_data;
1515 tANI_U8 *command = NULL;
1516 int ret = 0;
1517
1518 if (NULL == pAdapter)
1519 {
1520 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001521 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001522 ret = -ENODEV;
1523 goto exit;
1524 }
1525
Jeff Johnsone7245742012-09-05 17:12:55 -07001526 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001527 {
1528 ret = -EINVAL;
1529 goto exit;
1530 }
1531
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001532 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1533 {
1534 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1535 "%s:LOGP in Progress. Ignore!!!", __func__);
1536 ret = -EBUSY;
1537 goto exit;
1538 }
1539
Jeff Johnson295189b2012-06-20 16:38:30 -07001540 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1541 {
1542 ret = -EFAULT;
1543 goto exit;
1544 }
1545
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001546 if (priv_data.total_len <= 0)
1547 {
1548 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1549 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1550 priv_data.total_len);
1551 ret = -EINVAL;
1552 goto exit;
1553 }
1554
1555 /* Allocate +1 for '\0' */
1556 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001557 if (!command)
1558 {
1559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001560 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001561 ret = -ENOMEM;
1562 goto exit;
1563 }
1564
1565 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1566 {
1567 ret = -EFAULT;
1568 goto exit;
1569 }
1570
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001571 /* Making sure the command is NUL-terminated */
1572 command[priv_data.total_len] = '\0';
1573
Jeff Johnson295189b2012-06-20 16:38:30 -07001574 if ((SIOCDEVPRIVATE + 1) == cmd)
1575 {
1576 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1577
1578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001579 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001580
1581 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1582 {
1583 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1584 sizeof(tSirMacAddr)))
1585 {
1586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001587 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001588 ret = -EFAULT;
1589 }
1590 }
Amar Singhal0974e402013-02-12 14:27:46 -08001591 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001592 {
Amar Singhal0974e402013-02-12 14:27:46 -08001593 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001594 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001595
Jeff Johnson295189b2012-06-20 16:38:30 -07001596 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001597
1598 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001599 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001600 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001601 "%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 -07001602 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001603 ret = hdd_setBand_helper(dev, ptr);
1604 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001605 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1606 {
1607 char *country_code;
1608
1609 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001610
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001611 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001612 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301613 hdd_checkandupdate_phymode(pAdapter, country_code);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001614 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1615 (void *)(tSmeChangeCountryCallback)
1616 wlan_hdd_change_country_code_callback,
1617 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1618 if (eHAL_STATUS_SUCCESS == ret)
1619 {
1620 ret = wait_for_completion_interruptible_timeout(
1621 &pAdapter->change_country_code,
1622 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1623 if (0 >= ret)
1624 {
1625 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1626 __func__);
1627 }
1628 }
1629 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001630 {
1631 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001632 "%s: SME Change Country code fail ret=%d", __func__, ret);
1633 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001634 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001635
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001636 }
1637 /*
1638 command should be a string having format
1639 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1640 */
Amar Singhal0974e402013-02-12 14:27:46 -08001641 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001642 {
Amar Singhal0974e402013-02-12 14:27:46 -08001643 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001644
1645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001646 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001647
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001648 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001649 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001650 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1651 {
1652 int suspend = 0;
1653 tANI_U8 *ptr = (tANI_U8*)command + 15;
1654
1655 suspend = *ptr - '0';
1656 hdd_set_wlan_suspend_mode(suspend);
1657 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001658#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1659 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1660 {
1661 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001662 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001663 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1664 eHalStatus status = eHAL_STATUS_SUCCESS;
1665
1666 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1667 value = value + 15;
1668
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001669 /* Convert the value from ascii to integer */
1670 ret = kstrtos8(value, 10, &rssi);
1671 if (ret < 0)
1672 {
1673 /* If the input value is greater than max value of datatype, then also
1674 kstrtou8 fails */
1675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1676 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
1677 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1678 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1679 ret = -EINVAL;
1680 goto exit;
1681 }
1682
Srinivas Girigowdade697412013-02-14 16:31:48 -08001683 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001684
Srinivas Girigowdade697412013-02-14 16:31:48 -08001685 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1686 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1687 {
1688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1689 "Neighbor lookup threshold value %d is out of range"
1690 " (Min: %d Max: %d)", lookUpThreshold,
1691 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1692 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1693 ret = -EINVAL;
1694 goto exit;
1695 }
1696
1697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1698 "%s: Received Command to Set Roam trigger"
1699 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1700
1701 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1702 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1703 if (eHAL_STATUS_SUCCESS != status)
1704 {
1705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1706 "%s: Failed to set roam trigger, try again", __func__);
1707 ret = -EPERM;
1708 goto exit;
1709 }
1710
1711 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1712 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1713 }
1714 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1715 {
1716 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1717 int rssi = (-1) * lookUpThreshold;
1718 char extra[32];
1719 tANI_U8 len = 0;
1720
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001721 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001722 if (copy_to_user(priv_data.buf, &extra, len + 1))
1723 {
1724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1725 "%s: failed to copy data to user buffer", __func__);
1726 ret = -EFAULT;
1727 goto exit;
1728 }
1729 }
1730 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1731 {
1732 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001733 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001734 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001735
Srinivas Girigowdade697412013-02-14 16:31:48 -08001736 /* input refresh period is in terms of seconds */
1737 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1738 value = value + 18;
1739 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001740 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001741 if (ret < 0)
1742 {
1743 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001744 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001746 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001747 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001748 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1749 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001750 ret = -EINVAL;
1751 goto exit;
1752 }
1753
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001754 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1755 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001756 {
1757 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001758 "Roam scan period value %d is out of range"
1759 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001760 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1761 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001762 ret = -EINVAL;
1763 goto exit;
1764 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001765 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001766
1767 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1768 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001769 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001770
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001771 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1772 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001773 }
1774 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1775 {
1776 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1777 char extra[32];
1778 tANI_U8 len = 0;
1779
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001780 len = scnprintf(extra, sizeof(extra), "%s %d",
1781 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001782 /* Returned value is in units of seconds */
1783 if (copy_to_user(priv_data.buf, &extra, len + 1))
1784 {
1785 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1786 "%s: failed to copy data to user buffer", __func__);
1787 ret = -EFAULT;
1788 goto exit;
1789 }
1790 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001791 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1792 {
1793 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001794 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001795 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001796
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001797 /* input refresh period is in terms of seconds */
1798 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1799 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001800
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001801 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001802 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001803 if (ret < 0)
1804 {
1805 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001806 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001808 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001809 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001810 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1811 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1812 ret = -EINVAL;
1813 goto exit;
1814 }
1815
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001816 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1817 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1818 {
1819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1820 "Neighbor scan results refresh period value %d is out of range"
1821 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1822 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1823 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1824 ret = -EINVAL;
1825 goto exit;
1826 }
1827 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1828
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001829 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1830 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001831 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001832
1833 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1834 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1835 }
1836 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1837 {
1838 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1839 char extra[32];
1840 tANI_U8 len = 0;
1841
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001842 len = scnprintf(extra, sizeof(extra), "%s %d",
1843 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001844 /* Returned value is in units of seconds */
1845 if (copy_to_user(priv_data.buf, &extra, len + 1))
1846 {
1847 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1848 "%s: failed to copy data to user buffer", __func__);
1849 ret = -EFAULT;
1850 goto exit;
1851 }
1852 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001853#ifdef FEATURE_WLAN_LFR
1854 /* SETROAMMODE */
1855 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1856 {
1857 tANI_U8 *value = command;
1858 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1859
1860 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1861 value = value + SIZE_OF_SETROAMMODE + 1;
1862
1863 /* Convert the value from ascii to integer */
1864 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1865 if (ret < 0)
1866 {
1867 /* If the input value is greater than max value of datatype, then also
1868 kstrtou8 fails */
1869 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1870 "%s: kstrtou8 failed range [%d - %d]", __func__,
1871 CFG_LFR_FEATURE_ENABLED_MIN,
1872 CFG_LFR_FEATURE_ENABLED_MAX);
1873 ret = -EINVAL;
1874 goto exit;
1875 }
1876 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1877 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1878 {
1879 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1880 "Roam Mode value %d is out of range"
1881 " (Min: %d Max: %d)", roamMode,
1882 CFG_LFR_FEATURE_ENABLED_MIN,
1883 CFG_LFR_FEATURE_ENABLED_MAX);
1884 ret = -EINVAL;
1885 goto exit;
1886 }
1887
1888 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1889 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
1890 /*
1891 * Note that
1892 * SETROAMMODE 0 is to enable LFR while
1893 * SETROAMMODE 1 is to disable LFR, but
1894 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
1895 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
1896 */
1897 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1898 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
1899 else
1900 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
1901
1902 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
1903 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
1904 }
1905 /* GETROAMMODE */
1906 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
1907 {
1908 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1909 char extra[32];
1910 tANI_U8 len = 0;
1911
1912 /*
1913 * roamMode value shall be inverted because the sementics is different.
1914 */
1915 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1916 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
1917 else
1918 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
1919
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001920 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001921 if (copy_to_user(priv_data.buf, &extra, len + 1))
1922 {
1923 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1924 "%s: failed to copy data to user buffer", __func__);
1925 ret = -EFAULT;
1926 goto exit;
1927 }
1928 }
1929#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08001930#endif
1931#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1932 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1933 {
1934 tANI_U8 *value = command;
1935 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1936
1937 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1938 value = value + 13;
1939 /* Convert the value from ascii to integer */
1940 ret = kstrtou8(value, 10, &roamRssiDiff);
1941 if (ret < 0)
1942 {
1943 /* If the input value is greater than max value of datatype, then also
1944 kstrtou8 fails */
1945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1946 "%s: kstrtou8 failed range [%d - %d]", __func__,
1947 CFG_ROAM_RSSI_DIFF_MIN,
1948 CFG_ROAM_RSSI_DIFF_MAX);
1949 ret = -EINVAL;
1950 goto exit;
1951 }
1952
1953 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1954 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1955 {
1956 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1957 "Roam rssi diff value %d is out of range"
1958 " (Min: %d Max: %d)", roamRssiDiff,
1959 CFG_ROAM_RSSI_DIFF_MIN,
1960 CFG_ROAM_RSSI_DIFF_MAX);
1961 ret = -EINVAL;
1962 goto exit;
1963 }
1964
1965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1966 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1967
1968 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1969 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1970 }
1971 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1972 {
1973 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1974 char extra[32];
1975 tANI_U8 len = 0;
1976
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001977 len = scnprintf(extra, sizeof(extra), "%s %d",
1978 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001979 if (copy_to_user(priv_data.buf, &extra, len + 1))
1980 {
1981 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1982 "%s: failed to copy data to user buffer", __func__);
1983 ret = -EFAULT;
1984 goto exit;
1985 }
1986 }
1987#endif
1988#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1989 else if (strncmp(command, "GETBAND", 7) == 0)
1990 {
1991 int band = -1;
1992 char extra[32];
1993 tANI_U8 len = 0;
1994 hdd_getBand_helper(pHddCtx, &band);
1995
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001996 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001997 if (copy_to_user(priv_data.buf, &extra, len + 1))
1998 {
1999 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2000 "%s: failed to copy data to user buffer", __func__);
2001 ret = -EFAULT;
2002 goto exit;
2003 }
2004 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002005 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2006 {
2007 tANI_U8 *value = command;
2008 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2009 tANI_U8 numChannels = 0;
2010 eHalStatus status = eHAL_STATUS_SUCCESS;
2011
2012 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2013 if (eHAL_STATUS_SUCCESS != status)
2014 {
2015 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2016 "%s: Failed to parse channel list information", __func__);
2017 ret = -EINVAL;
2018 goto exit;
2019 }
2020
2021 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2022 {
2023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2024 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2025 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2026 ret = -EINVAL;
2027 goto exit;
2028 }
2029 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2030 numChannels);
2031 if (eHAL_STATUS_SUCCESS != status)
2032 {
2033 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2034 "%s: Failed to update channel list information", __func__);
2035 ret = -EINVAL;
2036 goto exit;
2037 }
2038 }
2039 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2040 {
2041 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2042 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002043 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002044 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002045 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002046
2047 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2048 ChannelList, &numChannels ))
2049 {
2050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2051 "%s: failed to get roam scan channel list", __func__);
2052 ret = -EFAULT;
2053 goto exit;
2054 }
2055 /* output channel list is of the format
2056 [Number of roam scan channels][Channel1][Channel2]... */
2057 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002058 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002059 for (j = 0; (j < numChannels); j++)
2060 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002061 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2062 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002063 }
2064
2065 if (copy_to_user(priv_data.buf, &extra, len + 1))
2066 {
2067 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2068 "%s: failed to copy data to user buffer", __func__);
2069 ret = -EFAULT;
2070 goto exit;
2071 }
2072 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002073 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2074 {
2075 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2076 char extra[32];
2077 tANI_U8 len = 0;
2078
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002079 /* Check if the features OKC/CCX/11R are supported simultaneously,
2080 then this operation is not permitted (return FAILURE) */
2081 if (ccxMode &&
2082 hdd_is_okc_mode_enabled(pHddCtx) &&
2083 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2084 {
2085 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2086 "%s: OKC/CCX/11R are supported simultaneously"
2087 " hence this operation is not permitted!", __func__);
2088 ret = -EPERM;
2089 goto exit;
2090 }
2091
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002092 len = scnprintf(extra, sizeof(extra), "%s %d",
2093 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002094 if (copy_to_user(priv_data.buf, &extra, len + 1))
2095 {
2096 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2097 "%s: failed to copy data to user buffer", __func__);
2098 ret = -EFAULT;
2099 goto exit;
2100 }
2101 }
2102 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2103 {
2104 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2105 char extra[32];
2106 tANI_U8 len = 0;
2107
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002108 /* Check if the features OKC/CCX/11R are supported simultaneously,
2109 then this operation is not permitted (return FAILURE) */
2110 if (okcMode &&
2111 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2112 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2113 {
2114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2115 "%s: OKC/CCX/11R are supported simultaneously"
2116 " hence this operation is not permitted!", __func__);
2117 ret = -EPERM;
2118 goto exit;
2119 }
2120
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002121 len = scnprintf(extra, sizeof(extra), "%s %d",
2122 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002123 if (copy_to_user(priv_data.buf, &extra, len + 1))
2124 {
2125 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2126 "%s: failed to copy data to user buffer", __func__);
2127 ret = -EFAULT;
2128 goto exit;
2129 }
2130 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002131 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002132 {
2133 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2134 char extra[32];
2135 tANI_U8 len = 0;
2136
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002137 len = scnprintf(extra, sizeof(extra), "%s %d",
2138 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002139 if (copy_to_user(priv_data.buf, &extra, len + 1))
2140 {
2141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2142 "%s: failed to copy data to user buffer", __func__);
2143 ret = -EFAULT;
2144 goto exit;
2145 }
2146 }
2147 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2148 {
2149 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2150 char extra[32];
2151 tANI_U8 len = 0;
2152
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002153 len = scnprintf(extra, sizeof(extra), "%s %d",
2154 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002155 if (copy_to_user(priv_data.buf, &extra, len + 1))
2156 {
2157 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2158 "%s: failed to copy data to user buffer", __func__);
2159 ret = -EFAULT;
2160 goto exit;
2161 }
2162 }
2163 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2164 {
2165 tANI_U8 *value = command;
2166 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2167
2168 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2169 value = value + 26;
2170 /* Convert the value from ascii to integer */
2171 ret = kstrtou8(value, 10, &minTime);
2172 if (ret < 0)
2173 {
2174 /* If the input value is greater than max value of datatype, then also
2175 kstrtou8 fails */
2176 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2177 "%s: kstrtou8 failed range [%d - %d]", __func__,
2178 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2179 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2180 ret = -EINVAL;
2181 goto exit;
2182 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002183 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2184 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2185 {
2186 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2187 "scan min channel time value %d is out of range"
2188 " (Min: %d Max: %d)", minTime,
2189 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2190 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2191 ret = -EINVAL;
2192 goto exit;
2193 }
2194
2195 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2196 "%s: Received Command to change channel min time = %d", __func__, minTime);
2197
2198 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2199 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2200 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002201 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2202 {
2203 tANI_U8 *value = command;
2204 tANI_U8 channel = 0;
2205 tANI_U8 dwellTime = 0;
2206 tANI_U8 bufLen = 0;
2207 tANI_U8 *buf = NULL;
2208 tSirMacAddr targetApBssid;
2209 eHalStatus status = eHAL_STATUS_SUCCESS;
2210 struct ieee80211_channel chan;
2211 tANI_U8 finalLen = 0;
2212 tANI_U8 *finalBuf = NULL;
2213 tANI_U8 temp = 0;
2214 u64 cookie;
2215 hdd_station_ctx_t *pHddStaCtx = NULL;
2216 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2217
2218 /* if not associated, no need to send action frame */
2219 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2220 {
2221 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2222 ret = -EINVAL;
2223 goto exit;
2224 }
2225
2226 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2227 &dwellTime, &buf, &bufLen);
2228 if (eHAL_STATUS_SUCCESS != status)
2229 {
2230 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2231 "%s: Failed to parse send action frame data", __func__);
2232 ret = -EINVAL;
2233 goto exit;
2234 }
2235
2236 /* if the target bssid is different from currently associated AP,
2237 then no need to send action frame */
2238 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2239 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2240 {
2241 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2242 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002243 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002244 goto exit;
2245 }
2246
2247 /* if the channel number is different from operating channel then
2248 no need to send action frame */
2249 if (channel != pHddStaCtx->conn_info.operationChannel)
2250 {
2251 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2252 "%s: channel(%d) is different from operating channel(%d)",
2253 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2254 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002255 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002256 goto exit;
2257 }
2258 chan.center_freq = sme_ChnToFreq(channel);
2259
2260 finalLen = bufLen + 24;
2261 finalBuf = vos_mem_malloc(finalLen);
2262 if (NULL == finalBuf)
2263 {
2264 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2265 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002266 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002267 goto exit;
2268 }
2269 vos_mem_zero(finalBuf, finalLen);
2270
2271 /* Fill subtype */
2272 temp = SIR_MAC_MGMT_ACTION << 4;
2273 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2274
2275 /* Fill type */
2276 temp = SIR_MAC_MGMT_FRAME;
2277 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2278
2279 /* Fill destination address (bssid of the AP) */
2280 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2281
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002282 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002283 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2284
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002285 /* Fill BSSID (AP mac address) */
2286 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002287
2288 /* Fill received buffer from 24th address */
2289 vos_mem_copy(finalBuf + 24, buf, bufLen);
2290
Jeff Johnson11c33152013-04-16 17:52:40 -07002291 /* done with the parsed buffer */
2292 vos_mem_free(buf);
2293
Yue Maf49ba872013-08-19 12:04:25 -07002294 wlan_hdd_action( NULL,
2295#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2296 &(pAdapter->wdev),
2297#else
2298 dev,
2299#endif
2300 &chan, 0,
2301#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2302 NL80211_CHAN_HT20, 1,
2303#endif
2304 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002305 1, &cookie );
2306 vos_mem_free(finalBuf);
2307 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002308 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2309 {
2310 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2311 char extra[32];
2312 tANI_U8 len = 0;
2313
2314 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002315 len = scnprintf(extra, sizeof(extra), "%s %d",
2316 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002317 if (copy_to_user(priv_data.buf, &extra, len + 1))
2318 {
2319 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2320 "%s: failed to copy data to user buffer", __func__);
2321 ret = -EFAULT;
2322 goto exit;
2323 }
2324 }
2325 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2326 {
2327 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002328 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002329 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002330
2331 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2332 value = value + 19;
2333 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002334 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002335 if (ret < 0)
2336 {
2337 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002338 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002339 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002340 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002341 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2342 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2343 ret = -EINVAL;
2344 goto exit;
2345 }
2346
2347 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2348 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2349 {
2350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2351 "lfr mode value %d is out of range"
2352 " (Min: %d Max: %d)", maxTime,
2353 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2354 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2355 ret = -EINVAL;
2356 goto exit;
2357 }
2358
2359 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2360 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2361
2362 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002363
2364 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2365 * where RFS is the RF Switching time. It is twice RFS to consider the
2366 * time to go off channel and return to the home channel. */
2367 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2368 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2369 {
2370 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2371 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
2372 " Hence enforcing home away time to disable (0)",
2373 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2374 homeAwayTime = 0;
2375 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2376 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2377 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002378 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2379 }
2380 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2381 {
2382 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2383 char extra[32];
2384 tANI_U8 len = 0;
2385
2386 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002387 len = scnprintf(extra, sizeof(extra), "%s %d",
2388 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002389 if (copy_to_user(priv_data.buf, &extra, len + 1))
2390 {
2391 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2392 "%s: failed to copy data to user buffer", __func__);
2393 ret = -EFAULT;
2394 goto exit;
2395 }
2396 }
2397 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2398 {
2399 tANI_U8 *value = command;
2400 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2401
2402 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2403 value = value + 16;
2404 /* Convert the value from ascii to integer */
2405 ret = kstrtou16(value, 10, &val);
2406 if (ret < 0)
2407 {
2408 /* If the input value is greater than max value of datatype, then also
2409 kstrtou16 fails */
2410 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2411 "%s: kstrtou16 failed range [%d - %d]", __func__,
2412 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2413 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2414 ret = -EINVAL;
2415 goto exit;
2416 }
2417
2418 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2419 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2420 {
2421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2422 "scan home time value %d is out of range"
2423 " (Min: %d Max: %d)", val,
2424 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2425 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2426 ret = -EINVAL;
2427 goto exit;
2428 }
2429
2430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2431 "%s: Received Command to change scan home time = %d", __func__, val);
2432
2433 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2434 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2435 }
2436 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2437 {
2438 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2439 char extra[32];
2440 tANI_U8 len = 0;
2441
2442 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002443 len = scnprintf(extra, sizeof(extra), "%s %d",
2444 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002445 if (copy_to_user(priv_data.buf, &extra, len + 1))
2446 {
2447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2448 "%s: failed to copy data to user buffer", __func__);
2449 ret = -EFAULT;
2450 goto exit;
2451 }
2452 }
2453 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2454 {
2455 tANI_U8 *value = command;
2456 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2457
2458 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2459 value = value + 17;
2460 /* Convert the value from ascii to integer */
2461 ret = kstrtou8(value, 10, &val);
2462 if (ret < 0)
2463 {
2464 /* If the input value is greater than max value of datatype, then also
2465 kstrtou8 fails */
2466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2467 "%s: kstrtou8 failed range [%d - %d]", __func__,
2468 CFG_ROAM_INTRA_BAND_MIN,
2469 CFG_ROAM_INTRA_BAND_MAX);
2470 ret = -EINVAL;
2471 goto exit;
2472 }
2473
2474 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2475 (val > CFG_ROAM_INTRA_BAND_MAX))
2476 {
2477 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2478 "intra band mode value %d is out of range"
2479 " (Min: %d Max: %d)", val,
2480 CFG_ROAM_INTRA_BAND_MIN,
2481 CFG_ROAM_INTRA_BAND_MAX);
2482 ret = -EINVAL;
2483 goto exit;
2484 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002485 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2486 "%s: Received Command to change intra band = %d", __func__, val);
2487
2488 pHddCtx->cfg_ini->nRoamIntraBand = val;
2489 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2490 }
2491 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2492 {
2493 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2494 char extra[32];
2495 tANI_U8 len = 0;
2496
2497 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002498 len = scnprintf(extra, sizeof(extra), "%s %d",
2499 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002500 if (copy_to_user(priv_data.buf, &extra, len + 1))
2501 {
2502 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2503 "%s: failed to copy data to user buffer", __func__);
2504 ret = -EFAULT;
2505 goto exit;
2506 }
2507 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002508 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2509 {
2510 tANI_U8 *value = command;
2511 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2512
2513 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2514 value = value + 15;
2515 /* Convert the value from ascii to integer */
2516 ret = kstrtou8(value, 10, &nProbes);
2517 if (ret < 0)
2518 {
2519 /* If the input value is greater than max value of datatype, then also
2520 kstrtou8 fails */
2521 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2522 "%s: kstrtou8 failed range [%d - %d]", __func__,
2523 CFG_ROAM_SCAN_N_PROBES_MIN,
2524 CFG_ROAM_SCAN_N_PROBES_MAX);
2525 ret = -EINVAL;
2526 goto exit;
2527 }
2528
2529 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2530 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2531 {
2532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2533 "NProbes value %d is out of range"
2534 " (Min: %d Max: %d)", nProbes,
2535 CFG_ROAM_SCAN_N_PROBES_MIN,
2536 CFG_ROAM_SCAN_N_PROBES_MAX);
2537 ret = -EINVAL;
2538 goto exit;
2539 }
2540
2541 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2542 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2543
2544 pHddCtx->cfg_ini->nProbes = nProbes;
2545 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2546 }
2547 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2548 {
2549 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2550 char extra[32];
2551 tANI_U8 len = 0;
2552
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002553 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002554 if (copy_to_user(priv_data.buf, &extra, len + 1))
2555 {
2556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2557 "%s: failed to copy data to user buffer", __func__);
2558 ret = -EFAULT;
2559 goto exit;
2560 }
2561 }
2562 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2563 {
2564 tANI_U8 *value = command;
2565 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002566 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002567
2568 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2569 /* input value is in units of msec */
2570 value = value + 20;
2571 /* Convert the value from ascii to integer */
2572 ret = kstrtou16(value, 10, &homeAwayTime);
2573 if (ret < 0)
2574 {
2575 /* If the input value is greater than max value of datatype, then also
2576 kstrtou8 fails */
2577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2578 "%s: kstrtou8 failed range [%d - %d]", __func__,
2579 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2580 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2581 ret = -EINVAL;
2582 goto exit;
2583 }
2584
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002585 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2586 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2587 {
2588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2589 "homeAwayTime value %d is out of range"
2590 " (Min: %d Max: %d)", homeAwayTime,
2591 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2592 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2593 ret = -EINVAL;
2594 goto exit;
2595 }
2596
2597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2598 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2599
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002600 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2601 * where RFS is the RF Switching time. It is twice RFS to consider the
2602 * time to go off channel and return to the home channel. */
2603 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2604 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2605 {
2606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2607 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)",
2608 " Hence enforcing home away time to disable (0)",
2609 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2610 homeAwayTime = 0;
2611 }
2612
2613 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2614 {
2615 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2616 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2617 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002618 }
2619 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2620 {
2621 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2622 char extra[32];
2623 tANI_U8 len = 0;
2624
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002625 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002626 if (copy_to_user(priv_data.buf, &extra, len + 1))
2627 {
2628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2629 "%s: failed to copy data to user buffer", __func__);
2630 ret = -EFAULT;
2631 goto exit;
2632 }
2633 }
2634 else if (strncmp(command, "REASSOC", 7) == 0)
2635 {
2636 tANI_U8 *value = command;
2637 tANI_U8 channel = 0;
2638 tSirMacAddr targetApBssid;
2639 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002640#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2641 tCsrHandoffRequest handoffInfo;
2642#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002643 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002644 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2645
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002646 /* if not associated, no need to proceed with reassoc */
2647 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2648 {
2649 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2650 ret = -EINVAL;
2651 goto exit;
2652 }
2653
2654 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2655 if (eHAL_STATUS_SUCCESS != status)
2656 {
2657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2658 "%s: Failed to parse reassoc command data", __func__);
2659 ret = -EINVAL;
2660 goto exit;
2661 }
2662
2663 /* if the target bssid is same as currently associated AP,
2664 then no need to proceed with reassoc */
2665 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2666 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2667 {
2668 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2669 ret = -EINVAL;
2670 goto exit;
2671 }
2672
2673 /* Check channel number is a valid channel number */
2674 if(VOS_STATUS_SUCCESS !=
2675 wlan_hdd_validate_operation_channel(pAdapter, channel))
2676 {
2677 hddLog(VOS_TRACE_LEVEL_ERROR,
2678 "%s: Invalid Channel [%d] \n", __func__, channel);
2679 return -EINVAL;
2680 }
2681
2682 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002683#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2684 handoffInfo.channel = channel;
2685 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2686 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2687#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002688 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002689 else if (strncmp(command, "SETWESMODE", 10) == 0)
2690 {
2691 tANI_U8 *value = command;
2692 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2693
2694 /* Move pointer to ahead of SETWESMODE<delimiter> */
2695 value = value + 11;
2696 /* Convert the value from ascii to integer */
2697 ret = kstrtou8(value, 10, &wesMode);
2698 if (ret < 0)
2699 {
2700 /* If the input value is greater than max value of datatype, then also
2701 kstrtou8 fails */
2702 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2703 "%s: kstrtou8 failed range [%d - %d]", __func__,
2704 CFG_ENABLE_WES_MODE_NAME_MIN,
2705 CFG_ENABLE_WES_MODE_NAME_MAX);
2706 ret = -EINVAL;
2707 goto exit;
2708 }
2709
2710 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2711 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2712 {
2713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2714 "WES Mode value %d is out of range"
2715 " (Min: %d Max: %d)", wesMode,
2716 CFG_ENABLE_WES_MODE_NAME_MIN,
2717 CFG_ENABLE_WES_MODE_NAME_MAX);
2718 ret = -EINVAL;
2719 goto exit;
2720 }
2721 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2722 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2723
2724 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2725 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2726 }
2727 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2728 {
2729 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2730 char extra[32];
2731 tANI_U8 len = 0;
2732
2733 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
2734 if (copy_to_user(priv_data.buf, &extra, len + 1))
2735 {
2736 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2737 "%s: failed to copy data to user buffer", __func__);
2738 ret = -EFAULT;
2739 goto exit;
2740 }
2741 }
2742#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002743#ifdef FEATURE_WLAN_LFR
2744 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2745 {
2746 tANI_U8 *value = command;
2747 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2748
2749 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2750 value = value + 12;
2751 /* Convert the value from ascii to integer */
2752 ret = kstrtou8(value, 10, &lfrMode);
2753 if (ret < 0)
2754 {
2755 /* If the input value is greater than max value of datatype, then also
2756 kstrtou8 fails */
2757 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2758 "%s: kstrtou8 failed range [%d - %d]", __func__,
2759 CFG_LFR_FEATURE_ENABLED_MIN,
2760 CFG_LFR_FEATURE_ENABLED_MAX);
2761 ret = -EINVAL;
2762 goto exit;
2763 }
2764
2765 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2766 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2767 {
2768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2769 "lfr mode value %d is out of range"
2770 " (Min: %d Max: %d)", lfrMode,
2771 CFG_LFR_FEATURE_ENABLED_MIN,
2772 CFG_LFR_FEATURE_ENABLED_MAX);
2773 ret = -EINVAL;
2774 goto exit;
2775 }
2776
2777 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2778 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2779
2780 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2781 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2782 }
2783#endif
2784#ifdef WLAN_FEATURE_VOWIFI_11R
2785 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2786 {
2787 tANI_U8 *value = command;
2788 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2789
2790 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2791 value = value + 18;
2792 /* Convert the value from ascii to integer */
2793 ret = kstrtou8(value, 10, &ft);
2794 if (ret < 0)
2795 {
2796 /* If the input value is greater than max value of datatype, then also
2797 kstrtou8 fails */
2798 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2799 "%s: kstrtou8 failed range [%d - %d]", __func__,
2800 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2801 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2802 ret = -EINVAL;
2803 goto exit;
2804 }
2805
2806 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2807 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2808 {
2809 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2810 "ft mode value %d is out of range"
2811 " (Min: %d Max: %d)", ft,
2812 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2813 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2814 ret = -EINVAL;
2815 goto exit;
2816 }
2817
2818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2819 "%s: Received Command to change ft mode = %d", __func__, ft);
2820
2821 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2822 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2823 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302824
2825 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2826 {
2827 tANI_U8 *value = command;
2828 tSirMacAddr targetApBssid;
2829 tANI_U8 trigger = 0;
2830 eHalStatus status = eHAL_STATUS_SUCCESS;
2831 hdd_station_ctx_t *pHddStaCtx = NULL;
2832 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2833
2834 /* if not associated, no need to proceed with reassoc */
2835 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2836 {
2837 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2838 ret = -EINVAL;
2839 goto exit;
2840 }
2841
2842 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2843 if (eHAL_STATUS_SUCCESS != status)
2844 {
2845 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2846 "%s: Failed to parse reassoc command data", __func__);
2847 ret = -EINVAL;
2848 goto exit;
2849 }
2850
2851 /* if the target bssid is same as currently associated AP,
2852 then no need to proceed with reassoc */
2853 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2854 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2855 {
2856 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2857 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2858 __func__);
2859 ret = -EINVAL;
2860 goto exit;
2861 }
2862
2863 /* Proceed with scan/roam */
2864 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2865 &targetApBssid[0],
2866 (tSmeFastRoamTrigger)(trigger));
2867 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002868#endif
2869#ifdef FEATURE_WLAN_CCX
2870 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2871 {
2872 tANI_U8 *value = command;
2873 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2874
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002875 /* Check if the features OKC/CCX/11R are supported simultaneously,
2876 then this operation is not permitted (return FAILURE) */
2877 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2878 hdd_is_okc_mode_enabled(pHddCtx) &&
2879 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2880 {
2881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2882 "%s: OKC/CCX/11R are supported simultaneously"
2883 " hence this operation is not permitted!", __func__);
2884 ret = -EPERM;
2885 goto exit;
2886 }
2887
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002888 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2889 value = value + 11;
2890 /* Convert the value from ascii to integer */
2891 ret = kstrtou8(value, 10, &ccxMode);
2892 if (ret < 0)
2893 {
2894 /* If the input value is greater than max value of datatype, then also
2895 kstrtou8 fails */
2896 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2897 "%s: kstrtou8 failed range [%d - %d]", __func__,
2898 CFG_CCX_FEATURE_ENABLED_MIN,
2899 CFG_CCX_FEATURE_ENABLED_MAX);
2900 ret = -EINVAL;
2901 goto exit;
2902 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002903 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2904 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2905 {
2906 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2907 "Ccx mode value %d is out of range"
2908 " (Min: %d Max: %d)", ccxMode,
2909 CFG_CCX_FEATURE_ENABLED_MIN,
2910 CFG_CCX_FEATURE_ENABLED_MAX);
2911 ret = -EINVAL;
2912 goto exit;
2913 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002914 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2915 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
2916
2917 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
2918 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
2919 }
2920#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002921 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
2922 {
2923 tANI_U8 *value = command;
2924 tANI_BOOLEAN roamScanControl = 0;
2925
2926 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
2927 value = value + 19;
2928 /* Convert the value from ascii to integer */
2929 ret = kstrtou8(value, 10, &roamScanControl);
2930 if (ret < 0)
2931 {
2932 /* If the input value is greater than max value of datatype, then also
2933 kstrtou8 fails */
2934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2935 "%s: kstrtou8 failed ", __func__);
2936 ret = -EINVAL;
2937 goto exit;
2938 }
2939
2940 if (0 != roamScanControl)
2941 {
2942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2943 "roam scan control invalid value = %d",
2944 roamScanControl);
2945 ret = -EINVAL;
2946 goto exit;
2947 }
2948 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2949 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
2950
2951 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
2952 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002953#ifdef FEATURE_WLAN_OKC
2954 else if (strncmp(command, "SETOKCMODE", 10) == 0)
2955 {
2956 tANI_U8 *value = command;
2957 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
2958
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002959 /* Check if the features OKC/CCX/11R are supported simultaneously,
2960 then this operation is not permitted (return FAILURE) */
2961 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2962 hdd_is_okc_mode_enabled(pHddCtx) &&
2963 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2964 {
2965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2966 "%s: OKC/CCX/11R are supported simultaneously"
2967 " hence this operation is not permitted!", __func__);
2968 ret = -EPERM;
2969 goto exit;
2970 }
2971
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002972 /* Move pointer to ahead of SETOKCMODE<delimiter> */
2973 value = value + 11;
2974 /* Convert the value from ascii to integer */
2975 ret = kstrtou8(value, 10, &okcMode);
2976 if (ret < 0)
2977 {
2978 /* If the input value is greater than max value of datatype, then also
2979 kstrtou8 fails */
2980 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2981 "%s: kstrtou8 failed range [%d - %d]", __func__,
2982 CFG_OKC_FEATURE_ENABLED_MIN,
2983 CFG_OKC_FEATURE_ENABLED_MAX);
2984 ret = -EINVAL;
2985 goto exit;
2986 }
2987
2988 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
2989 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
2990 {
2991 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2992 "Okc mode value %d is out of range"
2993 " (Min: %d Max: %d)", okcMode,
2994 CFG_OKC_FEATURE_ENABLED_MIN,
2995 CFG_OKC_FEATURE_ENABLED_MAX);
2996 ret = -EINVAL;
2997 goto exit;
2998 }
2999
3000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3001 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3002
3003 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3004 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003005#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003006 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3007 {
3008 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3009 char extra[32];
3010 tANI_U8 len = 0;
3011
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003012 len = scnprintf(extra, sizeof(extra), "%s %d",
3013 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003014 if (copy_to_user(priv_data.buf, &extra, len + 1))
3015 {
3016 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3017 "%s: failed to copy data to user buffer", __func__);
3018 ret = -EFAULT;
3019 goto exit;
3020 }
3021 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303022#ifdef WLAN_FEATURE_PACKET_FILTERING
3023 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3024 {
3025 tANI_U8 filterType = 0;
3026 tANI_U8 *value = command;
3027
3028 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3029 value = value + 22;
3030
3031 /* Convert the value from ascii to integer */
3032 ret = kstrtou8(value, 10, &filterType);
3033 if (ret < 0)
3034 {
3035 /* If the input value is greater than max value of datatype,
3036 * then also kstrtou8 fails
3037 */
3038 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3039 "%s: kstrtou8 failed range ", __func__);
3040 ret = -EINVAL;
3041 goto exit;
3042 }
3043
3044 if (filterType != 0 && filterType != 1)
3045 {
3046 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3047 "%s: Accepted Values are 0 and 1 ", __func__);
3048 ret = -EINVAL;
3049 goto exit;
3050 }
3051 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3052 pAdapter->sessionId);
3053 }
3054#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303055 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3056 {
3057 char *dhcpPhase;
3058 dhcpPhase = command + 12;
3059 if ('1' == *dhcpPhase)
3060 {
3061 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3062 pAdapter->macAddressCurrent.bytes);
3063 }
3064 else if ('2' == *dhcpPhase)
3065 {
3066 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3067 pAdapter->macAddressCurrent.bytes);
3068 }
3069 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003070 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3071 {
3072 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3073 }
3074 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3075 {
3076 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3077 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303078 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3079 {
3080 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3081 char extra[32];
3082 tANI_U8 len = 0;
3083
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003084 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303085 (int)pCfg->nActiveMaxChnTime);
3086 if (copy_to_user(priv_data.buf, &extra, len + 1))
3087 {
3088 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3089 "%s: failed to copy data to user buffer", __func__);
3090 ret = -EFAULT;
3091 goto exit;
3092 }
3093 ret = len;
3094 }
3095 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3096 {
3097 tANI_U8 *value = command;
3098 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3099 int val = 0, temp;
3100
3101 value = value + 13;
3102 temp = kstrtou32(value, 10, &val);
3103 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3104 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3105 {
3106 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3107 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3108 ret = -EFAULT;
3109 goto exit;
3110 }
3111 pCfg->nActiveMaxChnTime = val;
3112 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003113 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3114 {
3115 tANI_U8 filterType = 0;
3116 tANI_U8 *value;
3117 value = command + 9;
3118
3119 /* Convert the value from ascii to integer */
3120 ret = kstrtou8(value, 10, &filterType);
3121 if (ret < 0)
3122 {
3123 /* If the input value is greater than max value of datatype,
3124 * then also kstrtou8 fails
3125 */
3126 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3127 "%s: kstrtou8 failed range ", __func__);
3128 ret = -EINVAL;
3129 goto exit;
3130 }
3131 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3132 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3133 {
3134 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3135 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3136 " 2-Sink ", __func__);
3137 ret = -EINVAL;
3138 goto exit;
3139 }
3140 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3141 pHddCtx->drvr_miracast = filterType;
3142 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3143 }
Leo Chang614d2072013-08-22 14:59:44 -07003144 else if (strncmp(command, "SETMCRATE", 9) == 0)
3145 {
3146 int rc;
3147 tANI_U8 *value = command;
3148 int targetRate;
3149
3150 /* Only valid for SAP mode */
3151 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3152 {
3153 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3154 "%s: SAP mode is not running", __func__);
3155 ret = -EFAULT;
3156 goto exit;
3157 }
3158
3159 /* Move pointer to ahead of SETMCRATE<delimiter> */
3160 /* input value is in units of hundred kbps */
3161 value = value + 10;
3162 /* Convert the value from ascii to integer, decimal base */
3163 ret = kstrtouint(value, 10, &targetRate);
3164
3165 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
3166 if (rc)
3167 {
3168 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3169 "%s: Set MC Rate Fail %d", __func__, rc);
3170 ret = -EFAULT;
3171 goto exit;
3172 }
3173 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303174#ifdef FEATURE_WLAN_BATCH_SCAN
3175 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3176 {
3177 char extra[32];
3178 tANI_U8 len = 0;
3179 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3180
3181 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3182 {
3183 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3184 "%s: Batch scan feature is not supported by FW", __func__);
3185 ret = -EINVAL;
3186 goto exit;
3187 }
3188
3189 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3190 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3191 {
3192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3193 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3194 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3195 " mode",
3196 pAdapter->device_mode);
3197 ret = -EINVAL;
3198 goto exit;
3199 }
3200
3201 len = snprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
3202 version);
3203 if (copy_to_user(priv_data.buf, &extra, len + 1))
3204 {
3205 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3206 "%s: failed to copy data to user buffer", __func__);
3207 ret = -EFAULT;
3208 goto exit;
3209 }
3210 ret = HDD_BATCH_SCAN_VERSION;
3211 }
3212 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3213 {
3214 int status;
3215 tANI_U8 *value = (command + 16);
3216 eHalStatus halStatus;
3217 unsigned long rc;
3218 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3219 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3220
3221 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3222 {
3223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3224 "%s: Batch scan feature is not supported by FW", __func__);
3225 ret = -EINVAL;
3226 goto exit;
3227 }
3228
Rajeev Kumar20140c12013-10-21 19:39:02 -07003229
Rajeev79dbe4c2013-10-05 11:03:42 +05303230 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3231 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3232 {
3233 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003234 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303235 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3236 pAdapter->device_mode);
3237 ret = -EINVAL;
3238 goto exit;
3239 }
3240
Rajeev Kumar20140c12013-10-21 19:39:02 -07003241
Rajeev79dbe4c2013-10-05 11:03:42 +05303242 status = hdd_parse_set_batchscan_command(value, pReq);
3243 if (status)
3244 {
3245 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003246 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303247 ret = -EINVAL;
3248 goto exit;
3249 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003250
3251
Rajeev79dbe4c2013-10-05 11:03:42 +05303252 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3253 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3254 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3255 pAdapter);
3256
3257 if ( eHAL_STATUS_SUCCESS == halStatus )
3258 {
3259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3260 "sme_SetBatchScanReq returned success halStatus %d",
3261 halStatus);
3262 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3263 {
3264 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3265 rc = wait_for_completion_timeout(
3266 &pAdapter->hdd_set_batch_scan_req_var,
3267 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3268 if (0 == rc)
3269 {
3270 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3271 "%s: Timeout waiting for set batch scan to complete",
3272 __func__);
3273 ret = -EINVAL;
3274 goto exit;
3275 }
3276 }
3277 if ( !pRsp->nScansToBatch )
3278 {
3279 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3280 "%s: Received set batch scan failure response from FW",
3281 __func__, pRsp->nScansToBatch);
3282 ret = -EINVAL;
3283 goto exit;
3284 }
3285 /*As per the Batch Scan Framework API we should return the MIN of
3286 either MSCAN or the max # of scans firmware can cache*/
3287 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3288
Rajeev Kumar20140c12013-10-21 19:39:02 -07003289 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3290
Rajeev79dbe4c2013-10-05 11:03:42 +05303291 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3292 "%s: request MSCAN %d response MSCAN %d ret %d",
3293 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3294 }
3295 else
3296 {
3297 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3298 "sme_SetBatchScanReq returned failure halStatus %d",
3299 halStatus);
3300 ret = -EINVAL;
3301 goto exit;
3302 }
3303 }
3304 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3305 {
3306 eHalStatus halStatus;
3307 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3308 pInd->param = 0;
3309
3310 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3311 {
3312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3313 "%s: Batch scan feature is not supported by FW", __func__);
3314 ret = -EINVAL;
3315 goto exit;
3316 }
3317
Rajeev Kumar20140c12013-10-21 19:39:02 -07003318 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303319 {
3320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003321 "Batch scan is not yet enabled batch scan state %d",
3322 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303323 ret = -EINVAL;
3324 goto exit;
3325 }
3326
Rajeev Kumar20140c12013-10-21 19:39:02 -07003327 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3328
Rajeev79dbe4c2013-10-05 11:03:42 +05303329 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3330 pAdapter->sessionId);
3331 if ( eHAL_STATUS_SUCCESS == halStatus )
3332 {
3333 ret = 0;
3334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3335 "sme_StopBatchScanInd returned success halStatus %d",
3336 halStatus);
3337 }
3338 else
3339 {
3340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3341 "sme_StopBatchScanInd returned failure halStatus %d",
3342 halStatus);
3343 ret = -EINVAL;
3344 goto exit;
3345 }
3346 }
3347 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3348 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003349 tANI_U32 remain_len;
3350
Rajeev79dbe4c2013-10-05 11:03:42 +05303351 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3352 {
3353 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3354 "%s: Batch scan feature is not supported by FW", __func__);
3355 ret = -EINVAL;
3356 goto exit;
3357 }
3358
Rajeev Kumar20140c12013-10-21 19:39:02 -07003359 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303360 {
3361 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003362 "Batch scan is not yet enabled could not return results"
3363 "Batch Scan state %d",
3364 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303365 ret = -EINVAL;
3366 goto exit;
3367 }
3368
3369 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003370 remain_len = priv_data.total_len - priv_data.used_len;
3371 if (remain_len < priv_data.total_len)
3372 {
3373 /*Clear previous batch scan response data if any*/
3374 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3375 }
3376 else
3377 {
3378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3379 "Invalid total length from user space can't fetch batch"
3380 " scan response total_len %ld used_len %ld remain len %ld",
3381 priv_data.total_len, priv_data.used_len, remain_len);
3382 ret = -EINVAL;
3383 goto exit;
3384 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303385 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3386 }
3387#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003388#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3389 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3390 {
3391 tANI_U8 *value = command;
3392 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3393 tANI_U8 numChannels = 0;
3394 eHalStatus status = eHAL_STATUS_SUCCESS;
3395
3396 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3397 if (eHAL_STATUS_SUCCESS != status)
3398 {
3399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3400 "%s: Failed to parse channel list information", __func__);
3401 ret = -EINVAL;
3402 goto exit;
3403 }
3404
3405 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3406 {
3407 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3408 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3409 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3410 ret = -EINVAL;
3411 goto exit;
3412 }
3413 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3414 ChannelList,
3415 numChannels);
3416 if (eHAL_STATUS_SUCCESS != status)
3417 {
3418 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3419 "%s: Failed to update channel list information", __func__);
3420 ret = -EINVAL;
3421 goto exit;
3422 }
3423 }
3424 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3425 {
3426 tANI_U8 *value = command;
3427 char extra[128] = {0};
3428 int len = 0;
3429 tANI_U8 tid = 0;
3430 hdd_station_ctx_t *pHddStaCtx = NULL;
3431 tAniTrafStrmMetrics tsmMetrics;
3432 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3433
3434 /* if not associated, return error */
3435 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3436 {
3437 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3438 ret = -EINVAL;
3439 goto exit;
3440 }
3441
3442 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3443 value = value + 12;
3444 /* Convert the value from ascii to integer */
3445 ret = kstrtou8(value, 10, &tid);
3446 if (ret < 0)
3447 {
3448 /* If the input value is greater than max value of datatype, then also
3449 kstrtou8 fails */
3450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3451 "%s: kstrtou8 failed range [%d - %d]", __func__,
3452 TID_MIN_VALUE,
3453 TID_MAX_VALUE);
3454 ret = -EINVAL;
3455 goto exit;
3456 }
3457
3458 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3459 {
3460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3461 "tid value %d is out of range"
3462 " (Min: %d Max: %d)", tid,
3463 TID_MIN_VALUE,
3464 TID_MAX_VALUE);
3465 ret = -EINVAL;
3466 goto exit;
3467 }
3468
3469 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3470 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3471
3472 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3473 {
3474 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3475 "%s: failed to get tsm stats", __func__);
3476 ret = -EFAULT;
3477 goto exit;
3478 }
3479
3480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3481 "UplinkPktQueueDly(%d)\n"
3482 "UplinkPktQueueDlyHist[0](%d)\n"
3483 "UplinkPktQueueDlyHist[1](%d)\n"
3484 "UplinkPktQueueDlyHist[2](%d)\n"
3485 "UplinkPktQueueDlyHist[3](%d)\n"
3486 "UplinkPktTxDly(%lu)\n"
3487 "UplinkPktLoss(%d)\n"
3488 "UplinkPktCount(%d)\n"
3489 "RoamingCount(%d)\n"
3490 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3491 tsmMetrics.UplinkPktQueueDlyHist[0],
3492 tsmMetrics.UplinkPktQueueDlyHist[1],
3493 tsmMetrics.UplinkPktQueueDlyHist[2],
3494 tsmMetrics.UplinkPktQueueDlyHist[3],
3495 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3496 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3497
3498 /* Output TSM stats is of the format
3499 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3500 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
3501 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %lu %d %d %d %d", command,
3502 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3503 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3504 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3505 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3506 tsmMetrics.RoamingDly);
3507
3508 if (copy_to_user(priv_data.buf, &extra, len + 1))
3509 {
3510 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3511 "%s: failed to copy data to user buffer", __func__);
3512 ret = -EFAULT;
3513 goto exit;
3514 }
3515 }
3516 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3517 {
3518 tANI_U8 *value = command;
3519 tANI_U8 *cckmIe = NULL;
3520 tANI_U8 cckmIeLen = 0;
3521 eHalStatus status = eHAL_STATUS_SUCCESS;
3522
3523 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3524 if (eHAL_STATUS_SUCCESS != status)
3525 {
3526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3527 "%s: Failed to parse cckm ie data", __func__);
3528 ret = -EINVAL;
3529 goto exit;
3530 }
3531
3532 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3533 {
3534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3535 "%s: CCKM Ie input length is more than max[%d]", __func__,
3536 DOT11F_IE_RSN_MAX_LEN);
3537 if (NULL != cckmIe)
3538 {
3539 vos_mem_free(cckmIe);
3540 }
3541 ret = -EINVAL;
3542 goto exit;
3543 }
3544 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3545 if (NULL != cckmIe)
3546 {
3547 vos_mem_free(cckmIe);
3548 }
3549 }
3550#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003551 else {
3552 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3553 __func__, command);
3554 }
3555
Jeff Johnson295189b2012-06-20 16:38:30 -07003556 }
3557exit:
3558 if (command)
3559 {
3560 kfree(command);
3561 }
3562 return ret;
3563}
3564
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003565
3566
3567#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3568static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3569{
3570 struct statsContext *pStatsContext = NULL;
3571 hdd_adapter_t *pAdapter = NULL;
3572
3573 if (NULL == pContext)
3574 {
3575 hddLog(VOS_TRACE_LEVEL_ERROR,
3576 "%s: Bad param, pContext [%p]",
3577 __func__, pContext);
3578 return;
3579 }
3580
3581 /* there is a race condition that exists between this callback function
3582 and the caller since the caller could time out either before or
3583 while this code is executing. we'll assume the timeout hasn't
3584 occurred, but we'll verify that right before we save our work */
3585
3586 pStatsContext = pContext;
3587 pAdapter = pStatsContext->pAdapter;
3588 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3589 {
3590 /* the caller presumably timed out so there is nothing we can do */
3591 hddLog(VOS_TRACE_LEVEL_WARN,
3592 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3593 __func__, pAdapter, pStatsContext->magic);
3594 return;
3595 }
3596
3597 /* the race is on. caller could have timed out immediately after
3598 we verified the magic, but if so, caller will wait a short time
3599 for us to copy over the tsm stats */
3600 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3601 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3602 tsmMetrics.UplinkPktQueueDlyHist,
3603 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3604 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3605 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3606 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3607 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3608 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3609 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3610
3611 /* and notify the caller */
3612 complete(&pStatsContext->completion);
3613}
3614
3615
3616
3617static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3618 tAniTrafStrmMetrics* pTsmMetrics)
3619{
3620 hdd_station_ctx_t *pHddStaCtx = NULL;
3621 eHalStatus hstatus;
3622 long lrc;
3623 struct statsContext context;
3624 hdd_context_t *pHddCtx = NULL;
3625
3626 if (NULL == pAdapter)
3627 {
3628 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3629 return VOS_STATUS_E_FAULT;
3630 }
3631
3632 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3633 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3634
3635 /* we are connected prepare our callback context */
3636 init_completion(&context.completion);
3637 context.pAdapter = pAdapter;
3638 context.magic = STATS_CONTEXT_MAGIC;
3639
3640 /* query tsm stats */
3641 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3642 pHddStaCtx->conn_info.staId[ 0 ],
3643 pHddStaCtx->conn_info.bssId,
3644 &context, pHddCtx->pvosContext, tid);
3645
3646 if (eHAL_STATUS_SUCCESS != hstatus)
3647 {
3648 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3649 return hstatus;
3650 }
3651 else
3652 {
3653 /* request was sent -- wait for the response */
3654 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3655 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3656 /* either we have a response or we timed out
3657 either way, first invalidate our magic */
3658 context.magic = 0;
3659 if (lrc <= 0)
3660 {
3661 hddLog(VOS_TRACE_LEVEL_ERROR,
3662 "%s: SME %s while retrieving statistics",
3663 __func__, (0 == lrc) ? "timeout" : "interrupt");
3664 /* there is a race condition such that the callback
3665 function could be executing at the same time we are. of
3666 primary concern is if the callback function had already
3667 verified the "magic" but hasn't yet set the completion
3668 variable. Since the completion variable is on our
3669 stack, we'll delay just a bit to make sure the data is
3670 still valid if that is the case */
3671 msleep(50);
3672 return (VOS_STATUS_E_TIMEOUT);
3673 }
3674 }
3675 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3676 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3677 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3678 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3679 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3680 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3681 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3682 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3683 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3684 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3685
3686 return VOS_STATUS_SUCCESS;
3687}
3688#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3689
Srinivas Girigowdade697412013-02-14 16:31:48 -08003690#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3691void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3692{
3693 eCsrBand band = -1;
3694 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3695 switch (band)
3696 {
3697 case eCSR_BAND_ALL:
3698 *pBand = WLAN_HDD_UI_BAND_AUTO;
3699 break;
3700
3701 case eCSR_BAND_24:
3702 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3703 break;
3704
3705 case eCSR_BAND_5G:
3706 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3707 break;
3708
3709 default:
3710 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3711 *pBand = -1;
3712 break;
3713 }
3714}
3715
3716/**---------------------------------------------------------------------------
3717
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003718 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3719
3720 This function parses the send action frame data passed in the format
3721 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3722
Srinivas Girigowda56076852013-08-20 14:00:50 -07003723 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003724 \param - pTargetApBssid Pointer to target Ap bssid
3725 \param - pChannel Pointer to the Target AP channel
3726 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3727 \param - pBuf Pointer to data
3728 \param - pBufLen Pointer to data length
3729
3730 \return - 0 for success non-zero for failure
3731
3732 --------------------------------------------------------------------------*/
3733VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3734 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3735{
3736 tANI_U8 *inPtr = pValue;
3737 tANI_U8 *dataEnd;
3738 int tempInt;
3739 int j = 0;
3740 int i = 0;
3741 int v = 0;
3742 tANI_U8 tempBuf[32];
3743 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003744 /* 12 hexa decimal digits and 5 ':' */
3745 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003746
3747 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3748 /*no argument after the command*/
3749 if (NULL == inPtr)
3750 {
3751 return -EINVAL;
3752 }
3753
3754 /*no space after the command*/
3755 else if (SPACE_ASCII_VALUE != *inPtr)
3756 {
3757 return -EINVAL;
3758 }
3759
3760 /*removing empty spaces*/
3761 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3762
3763 /*no argument followed by spaces*/
3764 if ('\0' == *inPtr)
3765 {
3766 return -EINVAL;
3767 }
3768
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003769 v = sscanf(inPtr, "%17s", macAddress);
3770 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003771 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3773 "Invalid MAC address or All hex inputs are not read (%d)", v);
3774 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003775 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003776
3777 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3778 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3779 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3780 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3781 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3782 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003783
3784 /* point to the next argument */
3785 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3786 /*no argument after the command*/
3787 if (NULL == inPtr) return -EINVAL;
3788
3789 /*removing empty spaces*/
3790 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3791
3792 /*no argument followed by spaces*/
3793 if ('\0' == *inPtr)
3794 {
3795 return -EINVAL;
3796 }
3797
3798 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003799 v = sscanf(inPtr, "%32s ", tempBuf);
3800 if (1 != v) return -EINVAL;
3801
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003802 v = kstrtos32(tempBuf, 10, &tempInt);
3803 if ( v < 0) return -EINVAL;
3804
3805 *pChannel = tempInt;
3806
3807 /* point to the next argument */
3808 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3809 /*no argument after the command*/
3810 if (NULL == inPtr) return -EINVAL;
3811 /*removing empty spaces*/
3812 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3813
3814 /*no argument followed by spaces*/
3815 if ('\0' == *inPtr)
3816 {
3817 return -EINVAL;
3818 }
3819
3820 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003821 v = sscanf(inPtr, "%32s ", tempBuf);
3822 if (1 != v) return -EINVAL;
3823
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003824 v = kstrtos32(tempBuf, 10, &tempInt);
3825 if ( v < 0) return -EINVAL;
3826
3827 *pDwellTime = tempInt;
3828
3829 /* point to the next argument */
3830 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3831 /*no argument after the command*/
3832 if (NULL == inPtr) return -EINVAL;
3833 /*removing empty spaces*/
3834 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3835
3836 /*no argument followed by spaces*/
3837 if ('\0' == *inPtr)
3838 {
3839 return -EINVAL;
3840 }
3841
3842 /* find the length of data */
3843 dataEnd = inPtr;
3844 while(('\0' != *dataEnd) )
3845 {
3846 dataEnd++;
3847 ++(*pBufLen);
3848 }
3849 if ( *pBufLen <= 0) return -EINVAL;
3850
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07003851 /* Allocate the number of bytes based on the number of input characters
3852 whether it is even or odd.
3853 if the number of input characters are even, then we need N/2 byte.
3854 if the number of input characters are odd, then we need do (N+1)/2 to
3855 compensate rounding off.
3856 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
3857 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
3858 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003859 if (NULL == *pBuf)
3860 {
3861 hddLog(VOS_TRACE_LEVEL_FATAL,
3862 "%s: vos_mem_alloc failed ", __func__);
3863 return -EINVAL;
3864 }
3865
3866 /* the buffer received from the upper layer is character buffer,
3867 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
3868 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
3869 and f0 in 3rd location */
3870 for (i = 0, j = 0; j < *pBufLen; j += 2)
3871 {
3872 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
3873 (*pBuf)[i++] = tempByte;
3874 }
3875 *pBufLen = i;
3876 return VOS_STATUS_SUCCESS;
3877}
3878
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003879/**---------------------------------------------------------------------------
3880
Srinivas Girigowdade697412013-02-14 16:31:48 -08003881 \brief hdd_parse_channellist() - HDD Parse channel list
3882
3883 This function parses the channel list passed in the format
3884 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003885 if the Number of channels (N) does not match with the actual number of channels passed
3886 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
3887 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
3888 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
3889 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08003890
3891 \param - pValue Pointer to input channel list
3892 \param - ChannelList Pointer to local output array to record channel list
3893 \param - pNumChannels Pointer to number of roam scan channels
3894
3895 \return - 0 for success non-zero for failure
3896
3897 --------------------------------------------------------------------------*/
3898VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
3899{
3900 tANI_U8 *inPtr = pValue;
3901 int tempInt;
3902 int j = 0;
3903 int v = 0;
3904 char buf[32];
3905
3906 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3907 /*no argument after the command*/
3908 if (NULL == inPtr)
3909 {
3910 return -EINVAL;
3911 }
3912
3913 /*no space after the command*/
3914 else if (SPACE_ASCII_VALUE != *inPtr)
3915 {
3916 return -EINVAL;
3917 }
3918
3919 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003920 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003921
3922 /*no argument followed by spaces*/
3923 if ('\0' == *inPtr)
3924 {
3925 return -EINVAL;
3926 }
3927
3928 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003929 v = sscanf(inPtr, "%32s ", buf);
3930 if (1 != v) return -EINVAL;
3931
Srinivas Girigowdade697412013-02-14 16:31:48 -08003932 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003933 if ((v < 0) ||
3934 (tempInt <= 0) ||
3935 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
3936 {
3937 return -EINVAL;
3938 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003939
3940 *pNumChannels = tempInt;
3941
3942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3943 "Number of channels are: %d", *pNumChannels);
3944
3945 for (j = 0; j < (*pNumChannels); j++)
3946 {
3947 /*inPtr pointing to the beginning of first space after number of channels*/
3948 inPtr = strpbrk( inPtr, " " );
3949 /*no channel list after the number of channels argument*/
3950 if (NULL == inPtr)
3951 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003952 if (0 != j)
3953 {
3954 *pNumChannels = j;
3955 return VOS_STATUS_SUCCESS;
3956 }
3957 else
3958 {
3959 return -EINVAL;
3960 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003961 }
3962
3963 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003964 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003965
3966 /*no channel list after the number of channels argument and spaces*/
3967 if ( '\0' == *inPtr )
3968 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003969 if (0 != j)
3970 {
3971 *pNumChannels = j;
3972 return VOS_STATUS_SUCCESS;
3973 }
3974 else
3975 {
3976 return -EINVAL;
3977 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003978 }
3979
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003980 v = sscanf(inPtr, "%32s ", buf);
3981 if (1 != v) return -EINVAL;
3982
Srinivas Girigowdade697412013-02-14 16:31:48 -08003983 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003984 if ((v < 0) ||
3985 (tempInt <= 0) ||
3986 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3987 {
3988 return -EINVAL;
3989 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003990 pChannelList[j] = tempInt;
3991
3992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3993 "Channel %d added to preferred channel list",
3994 pChannelList[j] );
3995 }
3996
Srinivas Girigowdade697412013-02-14 16:31:48 -08003997 return VOS_STATUS_SUCCESS;
3998}
3999
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004000
4001/**---------------------------------------------------------------------------
4002
4003 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4004
4005 This function parses the reasoc command data passed in the format
4006 REASSOC<space><bssid><space><channel>
4007
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004008 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004009 \param - pTargetApBssid Pointer to target Ap bssid
4010 \param - pChannel Pointer to the Target AP channel
4011
4012 \return - 0 for success non-zero for failure
4013
4014 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004015VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4016 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004017{
4018 tANI_U8 *inPtr = pValue;
4019 int tempInt;
4020 int v = 0;
4021 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004022 /* 12 hexa decimal digits and 5 ':' */
4023 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004024
4025 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4026 /*no argument after the command*/
4027 if (NULL == inPtr)
4028 {
4029 return -EINVAL;
4030 }
4031
4032 /*no space after the command*/
4033 else if (SPACE_ASCII_VALUE != *inPtr)
4034 {
4035 return -EINVAL;
4036 }
4037
4038 /*removing empty spaces*/
4039 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4040
4041 /*no argument followed by spaces*/
4042 if ('\0' == *inPtr)
4043 {
4044 return -EINVAL;
4045 }
4046
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004047 v = sscanf(inPtr, "%17s", macAddress);
4048 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004049 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004050 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4051 "Invalid MAC address or All hex inputs are not read (%d)", v);
4052 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004053 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004054
4055 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4056 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4057 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4058 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4059 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4060 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004061
4062 /* point to the next argument */
4063 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4064 /*no argument after the command*/
4065 if (NULL == inPtr) return -EINVAL;
4066
4067 /*removing empty spaces*/
4068 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4069
4070 /*no argument followed by spaces*/
4071 if ('\0' == *inPtr)
4072 {
4073 return -EINVAL;
4074 }
4075
4076 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004077 v = sscanf(inPtr, "%32s ", tempBuf);
4078 if (1 != v) return -EINVAL;
4079
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004080 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004081 if ((v < 0) ||
4082 (tempInt <= 0) ||
4083 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4084 {
4085 return -EINVAL;
4086 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004087
4088 *pChannel = tempInt;
4089 return VOS_STATUS_SUCCESS;
4090}
4091
4092#endif
4093
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004094#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4095/**---------------------------------------------------------------------------
4096
4097 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4098
4099 This function parses the SETCCKM IE command
4100 SETCCKMIE<space><ie data>
4101
4102 \param - pValue Pointer to input data
4103 \param - pCckmIe Pointer to output cckm Ie
4104 \param - pCckmIeLen Pointer to output cckm ie length
4105
4106 \return - 0 for success non-zero for failure
4107
4108 --------------------------------------------------------------------------*/
4109VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4110 tANI_U8 *pCckmIeLen)
4111{
4112 tANI_U8 *inPtr = pValue;
4113 tANI_U8 *dataEnd;
4114 int j = 0;
4115 int i = 0;
4116 tANI_U8 tempByte = 0;
4117
4118 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4119 /*no argument after the command*/
4120 if (NULL == inPtr)
4121 {
4122 return -EINVAL;
4123 }
4124
4125 /*no space after the command*/
4126 else if (SPACE_ASCII_VALUE != *inPtr)
4127 {
4128 return -EINVAL;
4129 }
4130
4131 /*removing empty spaces*/
4132 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4133
4134 /*no argument followed by spaces*/
4135 if ('\0' == *inPtr)
4136 {
4137 return -EINVAL;
4138 }
4139
4140 /* find the length of data */
4141 dataEnd = inPtr;
4142 while(('\0' != *dataEnd) )
4143 {
4144 dataEnd++;
4145 ++(*pCckmIeLen);
4146 }
4147 if ( *pCckmIeLen <= 0) return -EINVAL;
4148
4149 /* Allocate the number of bytes based on the number of input characters
4150 whether it is even or odd.
4151 if the number of input characters are even, then we need N/2 byte.
4152 if the number of input characters are odd, then we need do (N+1)/2 to
4153 compensate rounding off.
4154 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4155 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4156 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4157 if (NULL == *pCckmIe)
4158 {
4159 hddLog(VOS_TRACE_LEVEL_FATAL,
4160 "%s: vos_mem_alloc failed ", __func__);
4161 return -EINVAL;
4162 }
4163 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4164 /* the buffer received from the upper layer is character buffer,
4165 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4166 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4167 and f0 in 3rd location */
4168 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4169 {
4170 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4171 (*pCckmIe)[i++] = tempByte;
4172 }
4173 *pCckmIeLen = i;
4174
4175 return VOS_STATUS_SUCCESS;
4176}
4177#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4178
Jeff Johnson295189b2012-06-20 16:38:30 -07004179/**---------------------------------------------------------------------------
4180
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004181 \brief hdd_is_valid_mac_address() - Validate MAC address
4182
4183 This function validates whether the given MAC address is valid or not
4184 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4185 where X is the hexa decimal digit character and separated by ':'
4186 This algorithm works even if MAC address is not separated by ':'
4187
4188 This code checks given input string mac contains exactly 12 hexadecimal digits.
4189 and a separator colon : appears in the input string only after
4190 an even number of hex digits.
4191
4192 \param - pMacAddr pointer to the input MAC address
4193 \return - 1 for valid and 0 for invalid
4194
4195 --------------------------------------------------------------------------*/
4196
4197v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4198{
4199 int xdigit = 0;
4200 int separator = 0;
4201 while (*pMacAddr)
4202 {
4203 if (isxdigit(*pMacAddr))
4204 {
4205 xdigit++;
4206 }
4207 else if (':' == *pMacAddr)
4208 {
4209 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4210 break;
4211
4212 ++separator;
4213 }
4214 else
4215 {
4216 separator = -1;
4217 /* Invalid MAC found */
4218 return 0;
4219 }
4220 ++pMacAddr;
4221 }
4222 return (xdigit == 12 && (separator == 5 || separator == 0));
4223}
4224
4225/**---------------------------------------------------------------------------
4226
Jeff Johnson295189b2012-06-20 16:38:30 -07004227 \brief hdd_open() - HDD Open function
4228
4229 This is called in response to ifconfig up
4230
4231 \param - dev Pointer to net_device structure
4232
4233 \return - 0 for success non-zero for failure
4234
4235 --------------------------------------------------------------------------*/
4236int hdd_open (struct net_device *dev)
4237{
4238 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4239 hdd_context_t *pHddCtx;
4240 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4241 VOS_STATUS status;
4242 v_BOOL_t in_standby = TRUE;
4243
4244 if (NULL == pAdapter)
4245 {
4246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004247 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004248 return -ENODEV;
4249 }
4250
4251 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4252 if (NULL == pHddCtx)
4253 {
4254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004255 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004256 return -ENODEV;
4257 }
4258
4259 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4260 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4261 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004262 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4263 {
4264 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304265 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004266 in_standby = FALSE;
4267 break;
4268 }
4269 else
4270 {
4271 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4272 pAdapterNode = pNext;
4273 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004274 }
4275
4276 if (TRUE == in_standby)
4277 {
4278 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4279 {
4280 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4281 "wlan out of power save", __func__);
4282 return -EINVAL;
4283 }
4284 }
4285
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004286 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004287 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4288 {
4289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004290 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004291 /* Enable TX queues only when we are connected */
4292 netif_tx_start_all_queues(dev);
4293 }
4294
4295 return 0;
4296}
4297
4298int hdd_mon_open (struct net_device *dev)
4299{
4300 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4301
4302 if(pAdapter == NULL) {
4303 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004304 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004305 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004306 }
4307
4308 netif_start_queue(dev);
4309
4310 return 0;
4311}
4312/**---------------------------------------------------------------------------
4313
4314 \brief hdd_stop() - HDD stop function
4315
4316 This is called in response to ifconfig down
4317
4318 \param - dev Pointer to net_device structure
4319
4320 \return - 0 for success non-zero for failure
4321
4322 --------------------------------------------------------------------------*/
4323
4324int hdd_stop (struct net_device *dev)
4325{
4326 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4327 hdd_context_t *pHddCtx;
4328 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4329 VOS_STATUS status;
4330 v_BOOL_t enter_standby = TRUE;
4331
4332 ENTER();
4333
4334 if (NULL == pAdapter)
4335 {
4336 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004337 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004338 return -ENODEV;
4339 }
4340
4341 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4342 if (NULL == pHddCtx)
4343 {
4344 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004345 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004346 return -ENODEV;
4347 }
4348
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004349 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004350 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4351 netif_tx_disable(pAdapter->dev);
4352 netif_carrier_off(pAdapter->dev);
4353
4354
4355 /* SoftAP ifaces should never go in power save mode
4356 making sure same here. */
4357 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4358 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004359 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004360 )
4361 {
4362 /* SoftAP mode, so return from here */
4363 EXIT();
4364 return 0;
4365 }
4366
4367 /* Find if any iface is up then
4368 if any iface is up then can't put device to sleep/ power save mode. */
4369 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4370 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4371 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004372 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4373 {
4374 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304375 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004376 enter_standby = FALSE;
4377 break;
4378 }
4379 else
4380 {
4381 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4382 pAdapterNode = pNext;
4383 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004384 }
4385
4386 if (TRUE == enter_standby)
4387 {
4388 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4389 "entering standby", __func__);
4390 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4391 {
4392 /*log and return success*/
4393 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4394 "wlan in power save", __func__);
4395 }
4396 }
4397
4398 EXIT();
4399 return 0;
4400}
4401
4402/**---------------------------------------------------------------------------
4403
4404 \brief hdd_uninit() - HDD uninit function
4405
4406 This is called during the netdev unregister to uninitialize all data
4407associated with the device
4408
4409 \param - dev Pointer to net_device structure
4410
4411 \return - void
4412
4413 --------------------------------------------------------------------------*/
4414static void hdd_uninit (struct net_device *dev)
4415{
4416 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4417
4418 ENTER();
4419
4420 do
4421 {
4422 if (NULL == pAdapter)
4423 {
4424 hddLog(VOS_TRACE_LEVEL_FATAL,
4425 "%s: NULL pAdapter", __func__);
4426 break;
4427 }
4428
4429 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4430 {
4431 hddLog(VOS_TRACE_LEVEL_FATAL,
4432 "%s: Invalid magic", __func__);
4433 break;
4434 }
4435
4436 if (NULL == pAdapter->pHddCtx)
4437 {
4438 hddLog(VOS_TRACE_LEVEL_FATAL,
4439 "%s: NULL pHddCtx", __func__);
4440 break;
4441 }
4442
4443 if (dev != pAdapter->dev)
4444 {
4445 hddLog(VOS_TRACE_LEVEL_FATAL,
4446 "%s: Invalid device reference", __func__);
4447 /* we haven't validated all cases so let this go for now */
4448 }
4449
4450 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4451
4452 /* after uninit our adapter structure will no longer be valid */
4453 pAdapter->dev = NULL;
4454 pAdapter->magic = 0;
4455 } while (0);
4456
4457 EXIT();
4458}
4459
4460/**---------------------------------------------------------------------------
4461
4462 \brief hdd_release_firmware() -
4463
4464 This function calls the release firmware API to free the firmware buffer.
4465
4466 \param - pFileName Pointer to the File Name.
4467 pCtx - Pointer to the adapter .
4468
4469
4470 \return - 0 for success, non zero for failure
4471
4472 --------------------------------------------------------------------------*/
4473
4474VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4475{
4476 VOS_STATUS status = VOS_STATUS_SUCCESS;
4477 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4478 ENTER();
4479
4480
4481 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4482
4483 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4484
4485 if(pHddCtx->fw) {
4486 release_firmware(pHddCtx->fw);
4487 pHddCtx->fw = NULL;
4488 }
4489 else
4490 status = VOS_STATUS_E_FAILURE;
4491 }
4492 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4493 if(pHddCtx->nv) {
4494 release_firmware(pHddCtx->nv);
4495 pHddCtx->nv = NULL;
4496 }
4497 else
4498 status = VOS_STATUS_E_FAILURE;
4499
4500 }
4501
4502 EXIT();
4503 return status;
4504}
4505
4506/**---------------------------------------------------------------------------
4507
4508 \brief hdd_request_firmware() -
4509
4510 This function reads the firmware file using the request firmware
4511 API and returns the the firmware data and the firmware file size.
4512
4513 \param - pfileName - Pointer to the file name.
4514 - pCtx - Pointer to the adapter .
4515 - ppfw_data - Pointer to the pointer of the firmware data.
4516 - pSize - Pointer to the file size.
4517
4518 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4519
4520 --------------------------------------------------------------------------*/
4521
4522
4523VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4524{
4525 int status;
4526 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4527 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4528 ENTER();
4529
4530 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4531
4532 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4533
4534 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4535 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4536 __func__, pfileName);
4537 retval = VOS_STATUS_E_FAILURE;
4538 }
4539
4540 else {
4541 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4542 *pSize = pHddCtx->fw->size;
4543 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4544 __func__, *pSize);
4545 }
4546 }
4547 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4548
4549 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4550
4551 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4552 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4553 __func__, pfileName);
4554 retval = VOS_STATUS_E_FAILURE;
4555 }
4556
4557 else {
4558 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4559 *pSize = pHddCtx->nv->size;
4560 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4561 __func__, *pSize);
4562 }
4563 }
4564
4565 EXIT();
4566 return retval;
4567}
4568/**---------------------------------------------------------------------------
4569 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4570
4571 This is the function invoked by SME to inform the result of a full power
4572 request issued by HDD
4573
4574 \param - callbackcontext - Pointer to cookie
4575 status - result of request
4576
4577 \return - None
4578
4579--------------------------------------------------------------------------*/
4580void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4581{
4582 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4583
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004584 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004585 if(&pHddCtx->full_pwr_comp_var)
4586 {
4587 complete(&pHddCtx->full_pwr_comp_var);
4588 }
4589}
4590
4591/**---------------------------------------------------------------------------
4592
4593 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4594
4595 This is the function invoked by SME to inform the result of BMPS
4596 request issued by HDD
4597
4598 \param - callbackcontext - Pointer to cookie
4599 status - result of request
4600
4601 \return - None
4602
4603--------------------------------------------------------------------------*/
4604void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4605{
4606
4607 struct completion *completion_var = (struct completion*) callbackContext;
4608
4609 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4610 if(completion_var != NULL)
4611 {
4612 complete(completion_var);
4613 }
4614}
4615
4616/**---------------------------------------------------------------------------
4617
4618 \brief hdd_get_cfg_file_size() -
4619
4620 This function reads the configuration file using the request firmware
4621 API and returns the configuration file size.
4622
4623 \param - pCtx - Pointer to the adapter .
4624 - pFileName - Pointer to the file name.
4625 - pBufSize - Pointer to the buffer size.
4626
4627 \return - 0 for success, non zero for failure
4628
4629 --------------------------------------------------------------------------*/
4630
4631VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4632{
4633 int status;
4634 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4635
4636 ENTER();
4637
4638 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4639
4640 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4641 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4642 status = VOS_STATUS_E_FAILURE;
4643 }
4644 else {
4645 *pBufSize = pHddCtx->fw->size;
4646 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4647 release_firmware(pHddCtx->fw);
4648 pHddCtx->fw = NULL;
4649 }
4650
4651 EXIT();
4652 return VOS_STATUS_SUCCESS;
4653}
4654
4655/**---------------------------------------------------------------------------
4656
4657 \brief hdd_read_cfg_file() -
4658
4659 This function reads the configuration file using the request firmware
4660 API and returns the cfg data and the buffer size of the configuration file.
4661
4662 \param - pCtx - Pointer to the adapter .
4663 - pFileName - Pointer to the file name.
4664 - pBuffer - Pointer to the data buffer.
4665 - pBufSize - Pointer to the buffer size.
4666
4667 \return - 0 for success, non zero for failure
4668
4669 --------------------------------------------------------------------------*/
4670
4671VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4672 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4673{
4674 int status;
4675 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4676
4677 ENTER();
4678
4679 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4680
4681 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4682 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4683 return VOS_STATUS_E_FAILURE;
4684 }
4685 else {
4686 if(*pBufSize != pHddCtx->fw->size) {
4687 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4688 "file size", __func__);
4689 release_firmware(pHddCtx->fw);
4690 pHddCtx->fw = NULL;
4691 return VOS_STATUS_E_FAILURE;
4692 }
4693 else {
4694 if(pBuffer) {
4695 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4696 }
4697 release_firmware(pHddCtx->fw);
4698 pHddCtx->fw = NULL;
4699 }
4700 }
4701
4702 EXIT();
4703
4704 return VOS_STATUS_SUCCESS;
4705}
4706
4707/**---------------------------------------------------------------------------
4708
Jeff Johnson295189b2012-06-20 16:38:30 -07004709 \brief hdd_set_mac_address() -
4710
4711 This function sets the user specified mac address using
4712 the command ifconfig wlanX hw ether <mac adress>.
4713
4714 \param - dev - Pointer to the net device.
4715 - addr - Pointer to the sockaddr.
4716 \return - 0 for success, non zero for failure
4717
4718 --------------------------------------------------------------------------*/
4719
4720static int hdd_set_mac_address(struct net_device *dev, void *addr)
4721{
4722 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4723 struct sockaddr *psta_mac_addr = addr;
4724 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4725
4726 ENTER();
4727
4728 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4729
4730#ifdef HDD_SESSIONIZE
4731 // set the MAC address though the STA ID CFG.
4732 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4733 (v_U8_t *)&pAdapter->macAddressCurrent,
4734 sizeof( pAdapter->macAddressCurrent ),
4735 hdd_set_mac_addr_cb, VOS_FALSE );
4736#endif
4737
4738 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4739
4740 EXIT();
4741 return halStatus;
4742}
4743
4744tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4745{
4746 int i;
4747 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4748 {
4749 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4750 break;
4751 }
4752
4753 if( VOS_MAX_CONCURRENCY_PERSONA == i)
4754 return NULL;
4755
4756 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
4757 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
4758}
4759
4760void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
4761{
4762 int i;
4763 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4764 {
4765 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
4766 {
4767 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
4768 break;
4769 }
4770 }
4771 return;
4772}
4773
4774#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4775 static struct net_device_ops wlan_drv_ops = {
4776 .ndo_open = hdd_open,
4777 .ndo_stop = hdd_stop,
4778 .ndo_uninit = hdd_uninit,
4779 .ndo_start_xmit = hdd_hard_start_xmit,
4780 .ndo_tx_timeout = hdd_tx_timeout,
4781 .ndo_get_stats = hdd_stats,
4782 .ndo_do_ioctl = hdd_ioctl,
4783 .ndo_set_mac_address = hdd_set_mac_address,
4784 .ndo_select_queue = hdd_select_queue,
4785#ifdef WLAN_FEATURE_PACKET_FILTERING
4786#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
4787 .ndo_set_rx_mode = hdd_set_multicast_list,
4788#else
4789 .ndo_set_multicast_list = hdd_set_multicast_list,
4790#endif //LINUX_VERSION_CODE
4791#endif
4792 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004793 static struct net_device_ops wlan_mon_drv_ops = {
4794 .ndo_open = hdd_mon_open,
4795 .ndo_stop = hdd_stop,
4796 .ndo_uninit = hdd_uninit,
4797 .ndo_start_xmit = hdd_mon_hard_start_xmit,
4798 .ndo_tx_timeout = hdd_tx_timeout,
4799 .ndo_get_stats = hdd_stats,
4800 .ndo_do_ioctl = hdd_ioctl,
4801 .ndo_set_mac_address = hdd_set_mac_address,
4802 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004803
4804#endif
4805
4806void hdd_set_station_ops( struct net_device *pWlanDev )
4807{
4808#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4809 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
4810 pWlanDev->netdev_ops = &wlan_drv_ops;
4811#else
4812 pWlanDev->open = hdd_open;
4813 pWlanDev->stop = hdd_stop;
4814 pWlanDev->uninit = hdd_uninit;
4815 pWlanDev->hard_start_xmit = NULL;
4816 pWlanDev->tx_timeout = hdd_tx_timeout;
4817 pWlanDev->get_stats = hdd_stats;
4818 pWlanDev->do_ioctl = hdd_ioctl;
4819 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
4820 pWlanDev->set_mac_address = hdd_set_mac_address;
4821#endif
4822}
4823
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004824static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07004825{
4826 struct net_device *pWlanDev = NULL;
4827 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004828 /*
4829 * cfg80211 initialization and registration....
4830 */
4831 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
4832
Jeff Johnson295189b2012-06-20 16:38:30 -07004833 if(pWlanDev != NULL)
4834 {
4835
4836 //Save the pointer to the net_device in the HDD adapter
4837 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
4838
Jeff Johnson295189b2012-06-20 16:38:30 -07004839 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
4840
4841 pAdapter->dev = pWlanDev;
4842 pAdapter->pHddCtx = pHddCtx;
4843 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
4844
4845 init_completion(&pAdapter->session_open_comp_var);
4846 init_completion(&pAdapter->session_close_comp_var);
4847 init_completion(&pAdapter->disconnect_comp_var);
4848 init_completion(&pAdapter->linkup_event_var);
4849 init_completion(&pAdapter->cancel_rem_on_chan_var);
4850 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004851#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4852 init_completion(&pAdapter->offchannel_tx_event);
4853#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004854 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004855#ifdef FEATURE_WLAN_TDLS
4856 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07004857 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08004858 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05304859 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004860#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004861 init_completion(&pHddCtx->mc_sus_event_var);
4862 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05304863 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07004864 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07004865 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07004866
Rajeev79dbe4c2013-10-05 11:03:42 +05304867#ifdef FEATURE_WLAN_BATCH_SCAN
4868 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
4869 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
4870 pAdapter->pBatchScanRsp = NULL;
4871 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07004872 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05304873 mutex_init(&pAdapter->hdd_batch_scan_lock);
4874#endif
4875
Jeff Johnson295189b2012-06-20 16:38:30 -07004876 pAdapter->isLinkUpSvcNeeded = FALSE;
4877 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
4878 //Init the net_device structure
4879 strlcpy(pWlanDev->name, name, IFNAMSIZ);
4880
4881 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
4882 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
4883 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
4884 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
4885
4886 hdd_set_station_ops( pAdapter->dev );
4887
4888 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004889 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
4890 pAdapter->wdev.wiphy = pHddCtx->wiphy;
4891 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004892 /* set pWlanDev's parent to underlying device */
4893 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
4894 }
4895
4896 return pAdapter;
4897}
4898
4899VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
4900{
4901 struct net_device *pWlanDev = pAdapter->dev;
4902 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4903 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4904 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4905
4906 if( rtnl_lock_held )
4907 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08004908 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07004909 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
4910 {
4911 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
4912 return VOS_STATUS_E_FAILURE;
4913 }
4914 }
4915 if (register_netdevice(pWlanDev))
4916 {
4917 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
4918 return VOS_STATUS_E_FAILURE;
4919 }
4920 }
4921 else
4922 {
4923 if(register_netdev(pWlanDev))
4924 {
4925 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
4926 return VOS_STATUS_E_FAILURE;
4927 }
4928 }
4929 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
4930
4931 return VOS_STATUS_SUCCESS;
4932}
4933
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004934static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07004935{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004936 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07004937
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004938 if (NULL == pAdapter)
4939 {
4940 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
4941 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07004942 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004943
4944 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4945 {
4946 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
4947 return eHAL_STATUS_NOT_INITIALIZED;
4948 }
4949
4950 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
4951
4952 /* need to make sure all of our scheduled work has completed.
4953 * This callback is called from MC thread context, so it is safe to
4954 * to call below flush workqueue API from here.
4955 */
4956 flush_scheduled_work();
4957
4958 /* We can be blocked while waiting for scheduled work to be
4959 * flushed, and the adapter structure can potentially be freed, in
4960 * which case the magic will have been reset. So make sure the
4961 * magic is still good, and hence the adapter structure is still
4962 * valid, before signaling completion */
4963 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
4964 {
4965 complete(&pAdapter->session_close_comp_var);
4966 }
4967
Jeff Johnson295189b2012-06-20 16:38:30 -07004968 return eHAL_STATUS_SUCCESS;
4969}
4970
4971VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
4972{
4973 struct net_device *pWlanDev = pAdapter->dev;
4974 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4975 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4976 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4977 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4978 int rc = 0;
4979
4980 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004981 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07004982 //Open a SME session for future operation
4983 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004984 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004985 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4986 {
4987 hddLog(VOS_TRACE_LEVEL_FATAL,
4988 "sme_OpenSession() failed with status code %08d [x%08lx]",
4989 halStatus, halStatus );
4990 status = VOS_STATUS_E_FAILURE;
4991 goto error_sme_open;
4992 }
4993
4994 //Block on a completion variable. Can't wait forever though.
4995 rc = wait_for_completion_interruptible_timeout(
4996 &pAdapter->session_open_comp_var,
4997 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4998 if (!rc)
4999 {
5000 hddLog(VOS_TRACE_LEVEL_FATAL,
5001 "Session is not opened within timeout period code %08d", rc );
5002 status = VOS_STATUS_E_FAILURE;
5003 goto error_sme_open;
5004 }
5005
5006 // Register wireless extensions
5007 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5008 {
5009 hddLog(VOS_TRACE_LEVEL_FATAL,
5010 "hdd_register_wext() failed with status code %08d [x%08lx]",
5011 halStatus, halStatus );
5012 status = VOS_STATUS_E_FAILURE;
5013 goto error_register_wext;
5014 }
5015 //Safe to register the hard_start_xmit function again
5016#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5017 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5018#else
5019 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5020#endif
5021
5022 //Set the Connection State to Not Connected
5023 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5024
5025 //Set the default operation channel
5026 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5027
5028 /* Make the default Auth Type as OPEN*/
5029 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5030
5031 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5032 {
5033 hddLog(VOS_TRACE_LEVEL_FATAL,
5034 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
5035 status, status );
5036 goto error_init_txrx;
5037 }
5038
5039 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5040
5041 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5042 {
5043 hddLog(VOS_TRACE_LEVEL_FATAL,
5044 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
5045 status, status );
5046 goto error_wmm_init;
5047 }
5048
5049 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5050
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005051#ifdef FEATURE_WLAN_TDLS
5052 if(0 != wlan_hdd_tdls_init(pAdapter))
5053 {
5054 status = VOS_STATUS_E_FAILURE;
5055 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5056 goto error_tdls_init;
5057 }
5058 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5059#endif
5060
Jeff Johnson295189b2012-06-20 16:38:30 -07005061 return VOS_STATUS_SUCCESS;
5062
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005063#ifdef FEATURE_WLAN_TDLS
5064error_tdls_init:
5065 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5066 hdd_wmm_adapter_close(pAdapter);
5067#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005068error_wmm_init:
5069 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5070 hdd_deinit_tx_rx(pAdapter);
5071error_init_txrx:
5072 hdd_UnregisterWext(pWlanDev);
5073error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005074 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005075 {
5076 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005077 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005078 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005079 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005080 {
5081 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005082 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005083 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005084 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005085 }
5086}
5087error_sme_open:
5088 return status;
5089}
5090
Jeff Johnson295189b2012-06-20 16:38:30 -07005091void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5092{
5093 hdd_cfg80211_state_t *cfgState;
5094
5095 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5096
5097 if( NULL != cfgState->buf )
5098 {
5099 int rc;
5100 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5101 rc = wait_for_completion_interruptible_timeout(
5102 &pAdapter->tx_action_cnf_event,
5103 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5104 if(!rc)
5105 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005106 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005107 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5108 }
5109 }
5110 return;
5111}
Jeff Johnson295189b2012-06-20 16:38:30 -07005112
5113void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5114{
5115 ENTER();
5116 switch ( pAdapter->device_mode )
5117 {
5118 case WLAN_HDD_INFRA_STATION:
5119 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005120 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005121 {
5122 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5123 {
5124 hdd_deinit_tx_rx( pAdapter );
5125 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5126 }
5127
5128 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5129 {
5130 hdd_wmm_adapter_close( pAdapter );
5131 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5132 }
5133
Jeff Johnson295189b2012-06-20 16:38:30 -07005134 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005135#ifdef FEATURE_WLAN_TDLS
5136 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5137 {
5138 wlan_hdd_tdls_exit(pAdapter);
5139 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5140 }
5141#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005142
5143 break;
5144 }
5145
5146 case WLAN_HDD_SOFTAP:
5147 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005148 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305149
5150 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5151 {
5152 hdd_wmm_adapter_close( pAdapter );
5153 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5154 }
5155
Jeff Johnson295189b2012-06-20 16:38:30 -07005156 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005157
5158 hdd_unregister_hostapd(pAdapter);
5159 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005160 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005161 break;
5162 }
5163
5164 case WLAN_HDD_MONITOR:
5165 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005166 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005167 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5168 {
5169 hdd_deinit_tx_rx( pAdapter );
5170 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5171 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005172 if(NULL != pAdapterforTx)
5173 {
5174 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5175 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005176 break;
5177 }
5178
5179
5180 default:
5181 break;
5182 }
5183
5184 EXIT();
5185}
5186
5187void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5188{
5189 struct net_device *pWlanDev = pAdapter->dev;
5190
Rajeev79dbe4c2013-10-05 11:03:42 +05305191#ifdef FEATURE_WLAN_BATCH_SCAN
5192 tHddBatchScanRsp *pNode;
5193 tHddBatchScanRsp *pPrev;
5194 if (pAdapter)
5195 {
5196 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5197 pNode = pAdapter->pBatchScanRsp;
5198 while (pNode)
5199 {
5200 pPrev = pNode;
5201 pNode = pNode->pNext;
5202 vos_mem_free((v_VOID_t * )pPrev);
5203 }
5204 pAdapter->pBatchScanRsp = NULL;
5205 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5206 }
5207#endif
5208
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5210 if( rtnl_held )
5211 {
5212 unregister_netdevice(pWlanDev);
5213 }
5214 else
5215 {
5216 unregister_netdev(pWlanDev);
5217 }
5218 // note that the pAdapter is no longer valid at this point
5219 // since the memory has been reclaimed
5220 }
5221
5222}
5223
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005224void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5225{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305226 VOS_STATUS status;
5227 hdd_adapter_t *pAdapter = NULL;
5228 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005229
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305230 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005231
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305232 /*loop through all adapters.*/
5233 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005234 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305235 pAdapter = pAdapterNode->pAdapter;
5236 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5237 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005238
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305239 { // we skip this registration for modes other than STA and P2P client modes.
5240 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5241 pAdapterNode = pNext;
5242 continue;
5243 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005244
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305245 //Apply Dynamic DTIM For P2P
5246 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5247 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5248 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5249 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5250 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5251 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5252 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5253 (eConnectionState_Associated ==
5254 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5255 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5256 {
5257 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005258
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305259 powerRequest.uIgnoreDTIM = 1;
5260 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5261
5262 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5263 {
5264 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5265 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5266 }
5267 else
5268 {
5269 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5270 }
5271
5272 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5273 * specified during Enter/Exit BMPS when LCD off*/
5274 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5275 NULL, eANI_BOOLEAN_FALSE);
5276 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5277 NULL, eANI_BOOLEAN_FALSE);
5278
5279 /* switch to the DTIM specified in cfg.ini */
5280 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5281 "Switch to DTIM %d", powerRequest.uListenInterval);
5282 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5283 break;
5284
5285 }
5286
5287 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5288 pAdapterNode = pNext;
5289 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005290}
5291
5292void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5293{
5294 /*Switch back to DTIM 1*/
5295 tSirSetPowerParamsReq powerRequest = { 0 };
5296
5297 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5298 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005299 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005300
5301 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5302 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5303 NULL, eANI_BOOLEAN_FALSE);
5304 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5305 NULL, eANI_BOOLEAN_FALSE);
5306
5307 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5308 "Switch to DTIM%d",powerRequest.uListenInterval);
5309 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5310
5311}
5312
Jeff Johnson295189b2012-06-20 16:38:30 -07005313VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5314{
5315 VOS_STATUS status = VOS_STATUS_SUCCESS;
5316
5317 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5318 {
5319 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5320 }
5321
5322 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5323 {
5324 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5325 }
5326
5327 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5328 {
5329 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5330 }
5331
5332 return status;
5333}
5334
5335VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5336{
5337 hdd_adapter_t *pAdapter = NULL;
5338 eHalStatus halStatus;
5339 VOS_STATUS status = VOS_STATUS_E_INVAL;
5340 v_BOOL_t disableBmps = FALSE;
5341 v_BOOL_t disableImps = FALSE;
5342
5343 switch(session_type)
5344 {
5345 case WLAN_HDD_INFRA_STATION:
5346 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005347 case WLAN_HDD_P2P_CLIENT:
5348 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005349 //Exit BMPS -> Is Sta/P2P Client is already connected
5350 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5351 if((NULL != pAdapter)&&
5352 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5353 {
5354 disableBmps = TRUE;
5355 }
5356
5357 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5358 if((NULL != pAdapter)&&
5359 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5360 {
5361 disableBmps = TRUE;
5362 }
5363
5364 //Exit both Bmps and Imps incase of Go/SAP Mode
5365 if((WLAN_HDD_SOFTAP == session_type) ||
5366 (WLAN_HDD_P2P_GO == session_type))
5367 {
5368 disableBmps = TRUE;
5369 disableImps = TRUE;
5370 }
5371
5372 if(TRUE == disableImps)
5373 {
5374 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5375 {
5376 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5377 }
5378 }
5379
5380 if(TRUE == disableBmps)
5381 {
5382 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5383 {
5384 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5385
5386 if(eHAL_STATUS_SUCCESS != halStatus)
5387 {
5388 status = VOS_STATUS_E_FAILURE;
5389 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5390 VOS_ASSERT(0);
5391 return status;
5392 }
5393 }
5394
5395 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5396 {
5397 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5398
5399 if(eHAL_STATUS_SUCCESS != halStatus)
5400 {
5401 status = VOS_STATUS_E_FAILURE;
5402 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5403 VOS_ASSERT(0);
5404 return status;
5405 }
5406 }
5407 }
5408
5409 if((TRUE == disableBmps) ||
5410 (TRUE == disableImps))
5411 {
5412 /* Now, get the chip into Full Power now */
5413 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5414 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5415 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5416
5417 if(halStatus != eHAL_STATUS_SUCCESS)
5418 {
5419 if(halStatus == eHAL_STATUS_PMC_PENDING)
5420 {
5421 //Block on a completion variable. Can't wait forever though
5422 wait_for_completion_interruptible_timeout(
5423 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5424 }
5425 else
5426 {
5427 status = VOS_STATUS_E_FAILURE;
5428 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5429 VOS_ASSERT(0);
5430 return status;
5431 }
5432 }
5433
5434 status = VOS_STATUS_SUCCESS;
5435 }
5436
5437 break;
5438 }
5439 return status;
5440}
5441
5442hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005443 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005444 tANI_U8 rtnl_held )
5445{
5446 hdd_adapter_t *pAdapter = NULL;
5447 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5448 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5449 VOS_STATUS exitbmpsStatus;
5450
5451 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5452
5453 //Disable BMPS incase of Concurrency
5454 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5455
5456 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5457 {
5458 //Fail to Exit BMPS
5459 VOS_ASSERT(0);
5460 return NULL;
5461 }
5462
5463 switch(session_type)
5464 {
5465 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005466 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005467 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005468 {
5469 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5470
5471 if( NULL == pAdapter )
5472 return NULL;
5473
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305474#ifdef FEATURE_WLAN_TDLS
5475 /* A Mutex Lock is introduced while changing/initializing the mode to
5476 * protect the concurrent access for the Adapters by TDLS module.
5477 */
5478 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5479 {
5480 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5481 "%s: unable to lock list", __func__);
5482 return NULL;
5483 }
5484#endif
5485
Jeff Johnsone7245742012-09-05 17:12:55 -07005486 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5487 NL80211_IFTYPE_P2P_CLIENT:
5488 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005489
Jeff Johnson295189b2012-06-20 16:38:30 -07005490 pAdapter->device_mode = session_type;
5491
5492 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305493#ifdef FEATURE_WLAN_TDLS
5494 mutex_unlock(&pHddCtx->tdls_lock);
5495#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005496 if( VOS_STATUS_SUCCESS != status )
5497 goto err_free_netdev;
5498
5499 status = hdd_register_interface( pAdapter, rtnl_held );
5500 if( VOS_STATUS_SUCCESS != status )
5501 {
5502 hdd_deinit_adapter(pHddCtx, pAdapter);
5503 goto err_free_netdev;
5504 }
5505 //Stop the Interface TX queue.
5506 netif_tx_disable(pAdapter->dev);
5507 //netif_tx_disable(pWlanDev);
5508 netif_carrier_off(pAdapter->dev);
5509
5510 break;
5511 }
5512
Jeff Johnson295189b2012-06-20 16:38:30 -07005513 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005514 case WLAN_HDD_SOFTAP:
5515 {
5516 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5517 if( NULL == pAdapter )
5518 return NULL;
5519
Jeff Johnson295189b2012-06-20 16:38:30 -07005520 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5521 NL80211_IFTYPE_AP:
5522 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005523 pAdapter->device_mode = session_type;
5524
5525 status = hdd_init_ap_mode(pAdapter);
5526 if( VOS_STATUS_SUCCESS != status )
5527 goto err_free_netdev;
5528
5529 status = hdd_register_hostapd( pAdapter, rtnl_held );
5530 if( VOS_STATUS_SUCCESS != status )
5531 {
5532 hdd_deinit_adapter(pHddCtx, pAdapter);
5533 goto err_free_netdev;
5534 }
5535
5536 netif_tx_disable(pAdapter->dev);
5537 netif_carrier_off(pAdapter->dev);
5538
5539 hdd_set_conparam( 1 );
5540 break;
5541 }
5542 case WLAN_HDD_MONITOR:
5543 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005544 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5545 if( NULL == pAdapter )
5546 return NULL;
5547
5548 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5549 pAdapter->device_mode = session_type;
5550 status = hdd_register_interface( pAdapter, rtnl_held );
5551#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5552 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5553#else
5554 pAdapter->dev->open = hdd_mon_open;
5555 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5556#endif
5557 hdd_init_tx_rx( pAdapter );
5558 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5559 //Set adapter to be used for data tx. It will use either GO or softap.
5560 pAdapter->sessionCtx.monitor.pAdapterForTx =
5561 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005562 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5563 {
5564 pAdapter->sessionCtx.monitor.pAdapterForTx =
5565 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5566 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005567 /* This workqueue will be used to transmit management packet over
5568 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005569 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5570 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5571 return NULL;
5572 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005573
Jeff Johnson295189b2012-06-20 16:38:30 -07005574 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5575 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005576 }
5577 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005578 case WLAN_HDD_FTM:
5579 {
5580 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5581
5582 if( NULL == pAdapter )
5583 return NULL;
5584 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5585 * message while loading driver in FTM mode. */
5586 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5587 pAdapter->device_mode = session_type;
5588 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305589
5590 hdd_init_tx_rx( pAdapter );
5591
5592 //Stop the Interface TX queue.
5593 netif_tx_disable(pAdapter->dev);
5594 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005595 }
5596 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005597 default:
5598 {
5599 VOS_ASSERT(0);
5600 return NULL;
5601 }
5602 }
5603
5604
5605 if( VOS_STATUS_SUCCESS == status )
5606 {
5607 //Add it to the hdd's session list.
5608 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5609 if( NULL == pHddAdapterNode )
5610 {
5611 status = VOS_STATUS_E_NOMEM;
5612 }
5613 else
5614 {
5615 pHddAdapterNode->pAdapter = pAdapter;
5616 status = hdd_add_adapter_back ( pHddCtx,
5617 pHddAdapterNode );
5618 }
5619 }
5620
5621 if( VOS_STATUS_SUCCESS != status )
5622 {
5623 if( NULL != pAdapter )
5624 {
5625 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5626 pAdapter = NULL;
5627 }
5628 if( NULL != pHddAdapterNode )
5629 {
5630 vos_mem_free( pHddAdapterNode );
5631 }
5632
5633 goto resume_bmps;
5634 }
5635
5636 if(VOS_STATUS_SUCCESS == status)
5637 {
5638 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5639
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005640 //Initialize the WoWL service
5641 if(!hdd_init_wowl(pAdapter))
5642 {
5643 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5644 goto err_free_netdev;
5645 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005646 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005647 return pAdapter;
5648
5649err_free_netdev:
5650 free_netdev(pAdapter->dev);
5651 wlan_hdd_release_intf_addr( pHddCtx,
5652 pAdapter->macAddressCurrent.bytes );
5653
5654resume_bmps:
5655 //If bmps disabled enable it
5656 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5657 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305658 if (pHddCtx->hdd_wlan_suspended)
5659 {
5660 hdd_set_pwrparams(pHddCtx);
5661 }
5662 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005663 }
5664 return NULL;
5665}
5666
5667VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5668 tANI_U8 rtnl_held )
5669{
5670 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5671 VOS_STATUS status;
5672
5673 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5674 if( VOS_STATUS_SUCCESS != status )
5675 return status;
5676
5677 while ( pCurrent->pAdapter != pAdapter )
5678 {
5679 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5680 if( VOS_STATUS_SUCCESS != status )
5681 break;
5682
5683 pCurrent = pNext;
5684 }
5685 pAdapterNode = pCurrent;
5686 if( VOS_STATUS_SUCCESS == status )
5687 {
5688 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5689 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305690
5691#ifdef FEATURE_WLAN_TDLS
5692
5693 /* A Mutex Lock is introduced while changing/initializing the mode to
5694 * protect the concurrent access for the Adapters by TDLS module.
5695 */
5696 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5697 {
5698 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5699 "%s: unable to lock list", __func__);
5700 return VOS_STATUS_E_FAILURE;
5701 }
5702#endif
5703
Jeff Johnson295189b2012-06-20 16:38:30 -07005704 hdd_remove_adapter( pHddCtx, pAdapterNode );
5705 vos_mem_free( pAdapterNode );
5706
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305707#ifdef FEATURE_WLAN_TDLS
5708 mutex_unlock(&pHddCtx->tdls_lock);
5709#endif
5710
Jeff Johnson295189b2012-06-20 16:38:30 -07005711
5712 /* If there is a single session of STA/P2P client, re-enable BMPS */
5713 if ((!vos_concurrent_sessions_running()) &&
5714 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5715 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5716 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305717 if (pHddCtx->hdd_wlan_suspended)
5718 {
5719 hdd_set_pwrparams(pHddCtx);
5720 }
5721 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005722 }
5723
5724 return VOS_STATUS_SUCCESS;
5725 }
5726
5727 return VOS_STATUS_E_FAILURE;
5728}
5729
5730VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5731{
5732 hdd_adapter_list_node_t *pHddAdapterNode;
5733 VOS_STATUS status;
5734
5735 ENTER();
5736
5737 do
5738 {
5739 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5740 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5741 {
5742 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
5743 vos_mem_free( pHddAdapterNode );
5744 }
5745 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
5746
5747 EXIT();
5748
5749 return VOS_STATUS_SUCCESS;
5750}
5751
5752void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
5753{
5754 v_U8_t addIE[1] = {0};
5755
5756 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5757 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
5758 eANI_BOOLEAN_FALSE) )
5759 {
5760 hddLog(LOGE,
5761 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
5762 }
5763
5764 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5765 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
5766 eANI_BOOLEAN_FALSE) )
5767 {
5768 hddLog(LOGE,
5769 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
5770 }
5771
5772 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5773 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
5774 eANI_BOOLEAN_FALSE) )
5775 {
5776 hddLog(LOGE,
5777 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
5778 }
5779}
5780
5781VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5782{
5783 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5784 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5785 union iwreq_data wrqu;
5786
5787 ENTER();
5788
5789 switch(pAdapter->device_mode)
5790 {
5791 case WLAN_HDD_INFRA_STATION:
5792 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005793 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005794 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5795 {
5796 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
5797 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5798 pAdapter->sessionId,
5799 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5800 else
5801 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5802 pAdapter->sessionId,
5803 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5804 //success implies disconnect command got queued up successfully
5805 if(halStatus == eHAL_STATUS_SUCCESS)
5806 {
5807 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
5808 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5809 }
5810 memset(&wrqu, '\0', sizeof(wrqu));
5811 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5812 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5813 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
5814 }
5815 else
5816 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305817 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005818 }
5819
5820 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
5821 {
5822 INIT_COMPLETION(pAdapter->session_close_comp_var);
5823 if (eHAL_STATUS_SUCCESS ==
5824 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
5825 hdd_smeCloseSessionCallback, pAdapter))
5826 {
5827 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005828 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005829 &pAdapter->session_close_comp_var,
5830 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5831 }
5832 }
5833
5834 break;
5835
5836 case WLAN_HDD_SOFTAP:
5837 case WLAN_HDD_P2P_GO:
5838 //Any softap specific cleanup here...
5839 mutex_lock(&pHddCtx->sap_lock);
5840 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5841 {
5842 VOS_STATUS status;
5843 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5844
5845 //Stop Bss.
5846 status = WLANSAP_StopBss(pHddCtx->pvosContext);
5847 if (VOS_IS_STATUS_SUCCESS(status))
5848 {
5849 hdd_hostapd_state_t *pHostapdState =
5850 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5851
5852 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
5853
5854 if (!VOS_IS_STATUS_SUCCESS(status))
5855 {
5856 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005857 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005858 }
5859 }
5860 else
5861 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005862 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005863 }
5864 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
5865
5866 if (eHAL_STATUS_FAILURE ==
5867 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5868 0, NULL, eANI_BOOLEAN_FALSE))
5869 {
5870 hddLog(LOGE,
5871 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005872 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005873 }
5874
5875 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
5876 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5877 eANI_BOOLEAN_FALSE) )
5878 {
5879 hddLog(LOGE,
5880 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
5881 }
5882
5883 // Reset WNI_CFG_PROBE_RSP Flags
5884 wlan_hdd_reset_prob_rspies(pAdapter);
5885 kfree(pAdapter->sessionCtx.ap.beacon);
5886 pAdapter->sessionCtx.ap.beacon = NULL;
5887 }
5888 mutex_unlock(&pHddCtx->sap_lock);
5889 break;
5890 case WLAN_HDD_MONITOR:
5891 break;
5892 default:
5893 break;
5894 }
5895
5896 EXIT();
5897 return VOS_STATUS_SUCCESS;
5898}
5899
5900VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
5901{
5902 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5903 VOS_STATUS status;
5904 hdd_adapter_t *pAdapter;
5905
5906 ENTER();
5907
5908 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5909
5910 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5911 {
5912 pAdapter = pAdapterNode->pAdapter;
5913 netif_tx_disable(pAdapter->dev);
5914 netif_carrier_off(pAdapter->dev);
5915
5916 hdd_stop_adapter( pHddCtx, pAdapter );
5917
5918 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5919 pAdapterNode = pNext;
5920 }
5921
5922 EXIT();
5923
5924 return VOS_STATUS_SUCCESS;
5925}
5926
5927VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
5928{
5929 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5930 VOS_STATUS status;
5931 hdd_adapter_t *pAdapter;
5932
5933 ENTER();
5934
5935 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5936
5937 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5938 {
5939 pAdapter = pAdapterNode->pAdapter;
5940 netif_tx_disable(pAdapter->dev);
5941 netif_carrier_off(pAdapter->dev);
5942
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005943 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
5944
Jeff Johnson295189b2012-06-20 16:38:30 -07005945 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305946 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5947 {
5948 hdd_wmm_adapter_close( pAdapter );
5949 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5950 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005951
5952 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5953 pAdapterNode = pNext;
5954 }
5955
5956 EXIT();
5957
5958 return VOS_STATUS_SUCCESS;
5959}
5960
5961VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
5962{
5963 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5964 VOS_STATUS status;
5965 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305966 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07005967
5968 ENTER();
5969
5970 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5971
5972 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5973 {
5974 pAdapter = pAdapterNode->pAdapter;
5975
5976 switch(pAdapter->device_mode)
5977 {
5978 case WLAN_HDD_INFRA_STATION:
5979 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005980 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305981
5982 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
5983
Jeff Johnson295189b2012-06-20 16:38:30 -07005984 hdd_init_station_mode(pAdapter);
5985 /* Open the gates for HDD to receive Wext commands */
5986 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005987 pHddCtx->scan_info.mScanPending = FALSE;
5988 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005989
5990 //Trigger the initial scan
5991 hdd_wlan_initial_scan(pAdapter);
5992
5993 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305994 if (eConnectionState_Associated == connState ||
5995 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07005996 {
5997 union iwreq_data wrqu;
5998 memset(&wrqu, '\0', sizeof(wrqu));
5999 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6000 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6001 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006002 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006003
Jeff Johnson295189b2012-06-20 16:38:30 -07006004 /* indicate disconnected event to nl80211 */
6005 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6006 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006007 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306008 else if (eConnectionState_Connecting == connState)
6009 {
6010 /*
6011 * Indicate connect failure to supplicant if we were in the
6012 * process of connecting
6013 */
6014 cfg80211_connect_result(pAdapter->dev, NULL,
6015 NULL, 0, NULL, 0,
6016 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6017 GFP_KERNEL);
6018 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006019 break;
6020
6021 case WLAN_HDD_SOFTAP:
6022 /* softAP can handle SSR */
6023 break;
6024
6025 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006026 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006027 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006028 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 break;
6030
6031 case WLAN_HDD_MONITOR:
6032 /* monitor interface start */
6033 break;
6034 default:
6035 break;
6036 }
6037
6038 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6039 pAdapterNode = pNext;
6040 }
6041
6042 EXIT();
6043
6044 return VOS_STATUS_SUCCESS;
6045}
6046
6047VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6048{
6049 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6050 hdd_adapter_t *pAdapter;
6051 VOS_STATUS status;
6052 v_U32_t roamId;
6053
6054 ENTER();
6055
6056 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6057
6058 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6059 {
6060 pAdapter = pAdapterNode->pAdapter;
6061
6062 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6063 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6064 {
6065 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6066 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6067
6068 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6069 init_completion(&pAdapter->disconnect_comp_var);
6070 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6071 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6072
6073 wait_for_completion_interruptible_timeout(
6074 &pAdapter->disconnect_comp_var,
6075 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6076
6077 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6078 pHddCtx->isAmpAllowed = VOS_FALSE;
6079 sme_RoamConnect(pHddCtx->hHal,
6080 pAdapter->sessionId, &(pWextState->roamProfile),
6081 &roamId);
6082 }
6083
6084 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6085 pAdapterNode = pNext;
6086 }
6087
6088 EXIT();
6089
6090 return VOS_STATUS_SUCCESS;
6091}
6092
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006093void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6094{
6095 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6096 VOS_STATUS status;
6097 hdd_adapter_t *pAdapter;
6098 hdd_station_ctx_t *pHddStaCtx;
6099 hdd_ap_ctx_t *pHddApCtx;
6100 hdd_hostapd_state_t * pHostapdState;
6101 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6102 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6103 const char *p2pMode = "DEV";
6104 const char *ccMode = "Standalone";
6105 int n;
6106
6107 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6108 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6109 {
6110 pAdapter = pAdapterNode->pAdapter;
6111 switch (pAdapter->device_mode) {
6112 case WLAN_HDD_INFRA_STATION:
6113 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6114 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6115 staChannel = pHddStaCtx->conn_info.operationChannel;
6116 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6117 }
6118 break;
6119 case WLAN_HDD_P2P_CLIENT:
6120 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6121 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6122 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6123 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6124 p2pMode = "CLI";
6125 }
6126 break;
6127 case WLAN_HDD_P2P_GO:
6128 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6129 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6130 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6131 p2pChannel = pHddApCtx->operatingChannel;
6132 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6133 }
6134 p2pMode = "GO";
6135 break;
6136 case WLAN_HDD_SOFTAP:
6137 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6138 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6139 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6140 apChannel = pHddApCtx->operatingChannel;
6141 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6142 }
6143 break;
6144 default:
6145 break;
6146 }
6147 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6148 pAdapterNode = pNext;
6149 }
6150 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6151 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6152 }
6153 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6154 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6155 if (p2pChannel > 0) {
6156 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6157 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6158 }
6159 if (apChannel > 0) {
6160 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6161 apChannel, MAC_ADDR_ARRAY(apBssid));
6162 }
6163
6164 if (p2pChannel > 0 && apChannel > 0) {
6165 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6166 }
6167}
6168
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006169bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006170{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006171 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006172}
6173
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006174/* Once SSR is disabled then it cannot be set. */
6175void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006176{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006177 if (HDD_SSR_DISABLED == isSsrRequired)
6178 return;
6179
Jeff Johnson295189b2012-06-20 16:38:30 -07006180 isSsrRequired = value;
6181}
6182
6183VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6184 hdd_adapter_list_node_t** ppAdapterNode)
6185{
6186 VOS_STATUS status;
6187 spin_lock(&pHddCtx->hddAdapters.lock);
6188 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6189 (hdd_list_node_t**) ppAdapterNode );
6190 spin_unlock(&pHddCtx->hddAdapters.lock);
6191 return status;
6192}
6193
6194VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6195 hdd_adapter_list_node_t* pAdapterNode,
6196 hdd_adapter_list_node_t** pNextAdapterNode)
6197{
6198 VOS_STATUS status;
6199 spin_lock(&pHddCtx->hddAdapters.lock);
6200 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6201 (hdd_list_node_t*) pAdapterNode,
6202 (hdd_list_node_t**)pNextAdapterNode );
6203
6204 spin_unlock(&pHddCtx->hddAdapters.lock);
6205 return status;
6206}
6207
6208VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6209 hdd_adapter_list_node_t* pAdapterNode)
6210{
6211 VOS_STATUS status;
6212 spin_lock(&pHddCtx->hddAdapters.lock);
6213 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6214 &pAdapterNode->node );
6215 spin_unlock(&pHddCtx->hddAdapters.lock);
6216 return status;
6217}
6218
6219VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6220 hdd_adapter_list_node_t** ppAdapterNode)
6221{
6222 VOS_STATUS status;
6223 spin_lock(&pHddCtx->hddAdapters.lock);
6224 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6225 (hdd_list_node_t**) ppAdapterNode );
6226 spin_unlock(&pHddCtx->hddAdapters.lock);
6227 return status;
6228}
6229
6230VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6231 hdd_adapter_list_node_t* pAdapterNode)
6232{
6233 VOS_STATUS status;
6234 spin_lock(&pHddCtx->hddAdapters.lock);
6235 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6236 (hdd_list_node_t*) pAdapterNode );
6237 spin_unlock(&pHddCtx->hddAdapters.lock);
6238 return status;
6239}
6240
6241VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6242 hdd_adapter_list_node_t* pAdapterNode)
6243{
6244 VOS_STATUS status;
6245 spin_lock(&pHddCtx->hddAdapters.lock);
6246 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6247 (hdd_list_node_t*) pAdapterNode );
6248 spin_unlock(&pHddCtx->hddAdapters.lock);
6249 return status;
6250}
6251
6252hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6253 tSirMacAddr macAddr )
6254{
6255 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6256 hdd_adapter_t *pAdapter;
6257 VOS_STATUS status;
6258
6259 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6260
6261 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6262 {
6263 pAdapter = pAdapterNode->pAdapter;
6264
6265 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6266 macAddr, sizeof(tSirMacAddr) ) )
6267 {
6268 return pAdapter;
6269 }
6270 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6271 pAdapterNode = pNext;
6272 }
6273
6274 return NULL;
6275
6276}
6277
6278hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6279{
6280 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6281 hdd_adapter_t *pAdapter;
6282 VOS_STATUS status;
6283
6284 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6285
6286 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6287 {
6288 pAdapter = pAdapterNode->pAdapter;
6289
6290 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6291 IFNAMSIZ ) )
6292 {
6293 return pAdapter;
6294 }
6295 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6296 pAdapterNode = pNext;
6297 }
6298
6299 return NULL;
6300
6301}
6302
6303hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6304{
6305 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6306 hdd_adapter_t *pAdapter;
6307 VOS_STATUS status;
6308
6309 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6310
6311 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6312 {
6313 pAdapter = pAdapterNode->pAdapter;
6314
6315 if( pAdapter && (mode == pAdapter->device_mode) )
6316 {
6317 return pAdapter;
6318 }
6319 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6320 pAdapterNode = pNext;
6321 }
6322
6323 return NULL;
6324
6325}
6326
6327//Remove this function later
6328hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6329{
6330 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6331 hdd_adapter_t *pAdapter;
6332 VOS_STATUS status;
6333
6334 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6335
6336 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6337 {
6338 pAdapter = pAdapterNode->pAdapter;
6339
6340 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6341 {
6342 return pAdapter;
6343 }
6344
6345 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6346 pAdapterNode = pNext;
6347 }
6348
6349 return NULL;
6350
6351}
6352
Jeff Johnson295189b2012-06-20 16:38:30 -07006353/**---------------------------------------------------------------------------
6354
6355 \brief hdd_set_monitor_tx_adapter() -
6356
6357 This API initializes the adapter to be used while transmitting on monitor
6358 adapter.
6359
6360 \param - pHddCtx - Pointer to the HDD context.
6361 pAdapter - Adapter that will used for TX. This can be NULL.
6362 \return - None.
6363 --------------------------------------------------------------------------*/
6364void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6365{
6366 hdd_adapter_t *pMonAdapter;
6367
6368 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6369
6370 if( NULL != pMonAdapter )
6371 {
6372 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6373 }
6374}
Jeff Johnson295189b2012-06-20 16:38:30 -07006375/**---------------------------------------------------------------------------
6376
6377 \brief hdd_select_queue() -
6378
6379 This API returns the operating channel of the requested device mode
6380
6381 \param - pHddCtx - Pointer to the HDD context.
6382 - mode - Device mode for which operating channel is required
6383 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6384 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6385 \return - channel number. "0" id the requested device is not found OR it is not connected.
6386 --------------------------------------------------------------------------*/
6387v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6388{
6389 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6390 VOS_STATUS status;
6391 hdd_adapter_t *pAdapter;
6392 v_U8_t operatingChannel = 0;
6393
6394 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6395
6396 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6397 {
6398 pAdapter = pAdapterNode->pAdapter;
6399
6400 if( mode == pAdapter->device_mode )
6401 {
6402 switch(pAdapter->device_mode)
6403 {
6404 case WLAN_HDD_INFRA_STATION:
6405 case WLAN_HDD_P2P_CLIENT:
6406 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6407 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6408 break;
6409 case WLAN_HDD_SOFTAP:
6410 case WLAN_HDD_P2P_GO:
6411 /*softap connection info */
6412 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6413 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6414 break;
6415 default:
6416 break;
6417 }
6418
6419 break; //Found the device of interest. break the loop
6420 }
6421
6422 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6423 pAdapterNode = pNext;
6424 }
6425 return operatingChannel;
6426}
6427
6428#ifdef WLAN_FEATURE_PACKET_FILTERING
6429/**---------------------------------------------------------------------------
6430
6431 \brief hdd_set_multicast_list() -
6432
6433 This used to set the multicast address list.
6434
6435 \param - dev - Pointer to the WLAN device.
6436 - skb - Pointer to OS packet (sk_buff).
6437 \return - success/fail
6438
6439 --------------------------------------------------------------------------*/
6440static void hdd_set_multicast_list(struct net_device *dev)
6441{
6442 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006443 int mc_count;
6444 int i = 0;
6445 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306446
6447 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006448 {
6449 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306450 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006451 return;
6452 }
6453
6454 if (dev->flags & IFF_ALLMULTI)
6455 {
6456 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006457 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306458 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006459 }
6460 else
6461 {
6462 mc_count = netdev_mc_count(dev);
6463 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006464 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006465 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6466 {
6467 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006468 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306469 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006470 return;
6471 }
6472
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306473 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006474
6475 netdev_for_each_mc_addr(ha, dev) {
6476 if (i == mc_count)
6477 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306478 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6479 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6480 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006481 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306482 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006483 i++;
6484 }
6485 }
6486 return;
6487}
6488#endif
6489
6490/**---------------------------------------------------------------------------
6491
6492 \brief hdd_select_queue() -
6493
6494 This function is registered with the Linux OS for network
6495 core to decide which queue to use first.
6496
6497 \param - dev - Pointer to the WLAN device.
6498 - skb - Pointer to OS packet (sk_buff).
6499 \return - ac, Queue Index/access category corresponding to UP in IP header
6500
6501 --------------------------------------------------------------------------*/
6502v_U16_t hdd_select_queue(struct net_device *dev,
6503 struct sk_buff *skb)
6504{
6505 return hdd_wmm_select_queue(dev, skb);
6506}
6507
6508
6509/**---------------------------------------------------------------------------
6510
6511 \brief hdd_wlan_initial_scan() -
6512
6513 This function triggers the initial scan
6514
6515 \param - pAdapter - Pointer to the HDD adapter.
6516
6517 --------------------------------------------------------------------------*/
6518void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6519{
6520 tCsrScanRequest scanReq;
6521 tCsrChannelInfo channelInfo;
6522 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006523 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006524 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6525
6526 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6527 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6528 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6529
6530 if(sme_Is11dSupported(pHddCtx->hHal))
6531 {
6532 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6533 if ( HAL_STATUS_SUCCESS( halStatus ) )
6534 {
6535 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6536 if( !scanReq.ChannelInfo.ChannelList )
6537 {
6538 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6539 vos_mem_free(channelInfo.ChannelList);
6540 return;
6541 }
6542 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6543 channelInfo.numOfChannels);
6544 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6545 vos_mem_free(channelInfo.ChannelList);
6546 }
6547
6548 scanReq.scanType = eSIR_PASSIVE_SCAN;
6549 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6550 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6551 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6552 }
6553 else
6554 {
6555 scanReq.scanType = eSIR_ACTIVE_SCAN;
6556 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6557 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6558 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6559 }
6560
6561 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6562 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6563 {
6564 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6565 __func__, halStatus );
6566 }
6567
6568 if(sme_Is11dSupported(pHddCtx->hHal))
6569 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6570}
6571
6572struct fullPowerContext
6573{
6574 struct completion completion;
6575 unsigned int magic;
6576};
6577#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6578
6579/**---------------------------------------------------------------------------
6580
6581 \brief hdd_full_power_callback() - HDD full power callback function
6582
6583 This is the function invoked by SME to inform the result of a full power
6584 request issued by HDD
6585
6586 \param - callbackcontext - Pointer to cookie
6587 \param - status - result of request
6588
6589 \return - None
6590
6591 --------------------------------------------------------------------------*/
6592static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6593{
6594 struct fullPowerContext *pContext = callbackContext;
6595
6596 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306597 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006598
6599 if (NULL == callbackContext)
6600 {
6601 hddLog(VOS_TRACE_LEVEL_ERROR,
6602 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006603 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006604 return;
6605 }
6606
6607 /* there is a race condition that exists between this callback function
6608 and the caller since the caller could time out either before or
6609 while this code is executing. we'll assume the timeout hasn't
6610 occurred, but we'll verify that right before we save our work */
6611
6612 if (POWER_CONTEXT_MAGIC != pContext->magic)
6613 {
6614 /* the caller presumably timed out so there is nothing we can do */
6615 hddLog(VOS_TRACE_LEVEL_WARN,
6616 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006617 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006618 return;
6619 }
6620
6621 /* the race is on. caller could have timed out immediately after
6622 we verified the magic, but if so, caller will wait a short time
6623 for us to notify the caller, so the context will stay valid */
6624 complete(&pContext->completion);
6625}
6626
6627/**---------------------------------------------------------------------------
6628
6629 \brief hdd_wlan_exit() - HDD WLAN exit function
6630
6631 This is the driver exit point (invoked during rmmod)
6632
6633 \param - pHddCtx - Pointer to the HDD Context
6634
6635 \return - None
6636
6637 --------------------------------------------------------------------------*/
6638void hdd_wlan_exit(hdd_context_t *pHddCtx)
6639{
6640 eHalStatus halStatus;
6641 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6642 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306643 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006644 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006645 struct fullPowerContext powerContext;
6646 long lrc;
6647
6648 ENTER();
6649
Jeff Johnson88ba7742013-02-27 14:36:02 -08006650 if (VOS_FTM_MODE != hdd_get_conparam())
6651 {
6652 // Unloading, restart logic is no more required.
6653 wlan_hdd_restart_deinit(pHddCtx);
6654 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006655
Jeff Johnson295189b2012-06-20 16:38:30 -07006656 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006657 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006658 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006659 {
6660 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6661 WLAN_HDD_INFRA_STATION);
6662 if (pAdapter == NULL)
6663 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6664
6665 if (pAdapter != NULL)
6666 {
6667 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6668 hdd_UnregisterWext(pAdapter->dev);
6669 }
6670 }
6671 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006672
Jeff Johnson295189b2012-06-20 16:38:30 -07006673 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006674 {
6675 wlan_hdd_ftm_close(pHddCtx);
6676 goto free_hdd_ctx;
6677 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006678 //Stop the Interface TX queue.
6679 //netif_tx_disable(pWlanDev);
6680 //netif_carrier_off(pWlanDev);
6681
Jeff Johnson295189b2012-06-20 16:38:30 -07006682 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6683 {
6684 pAdapter = hdd_get_adapter(pHddCtx,
6685 WLAN_HDD_SOFTAP);
6686 }
6687 else
6688 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006689 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006690 {
6691 pAdapter = hdd_get_adapter(pHddCtx,
6692 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006693 if (pAdapter == NULL)
6694 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006695 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006696 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006697 /* DeRegister with platform driver as client for Suspend/Resume */
6698 vosStatus = hddDeregisterPmOps(pHddCtx);
6699 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6700 {
6701 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6702 VOS_ASSERT(0);
6703 }
6704
6705 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6706 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6707 {
6708 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6709 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006710
6711 // Cancel any outstanding scan requests. We are about to close all
6712 // of our adapters, but an adapter structure is what SME passes back
6713 // to our callback function. Hence if there are any outstanding scan
6714 // requests then there is a race condition between when the adapter
6715 // is closed and when the callback is invoked. We try to resolve that
6716 // race condition here by canceling any outstanding scans before we
6717 // close the adapters.
6718 // Note that the scans may be cancelled in an asynchronous manner, so
6719 // ideally there needs to be some kind of synchronization. Rather than
6720 // introduce a new synchronization here, we will utilize the fact that
6721 // we are about to Request Full Power, and since that is synchronized,
6722 // the expectation is that by the time Request Full Power has completed,
6723 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006724 if (NULL != pAdapter)
6725 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6726 else
6727 hddLog(VOS_TRACE_LEVEL_ERROR,
6728 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006729
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006730 //Stop the traffic monitor timer
6731 if ( VOS_TIMER_STATE_RUNNING ==
6732 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6733 {
6734 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6735 }
6736
6737 // Destroy the traffic monitor timer
6738 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
6739 &pHddCtx->tx_rx_trafficTmr)))
6740 {
6741 hddLog(VOS_TRACE_LEVEL_ERROR,
6742 "%s: Cannot deallocate Traffic monitor timer", __func__);
6743 }
6744
Jeff Johnson295189b2012-06-20 16:38:30 -07006745 //Disable IMPS/BMPS as we do not want the device to enter any power
6746 //save mode during shutdown
6747 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6748 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6749 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
6750
6751 //Ensure that device is in full power as we will touch H/W during vos_Stop
6752 init_completion(&powerContext.completion);
6753 powerContext.magic = POWER_CONTEXT_MAGIC;
6754
6755 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
6756 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
6757
6758 if (eHAL_STATUS_SUCCESS != halStatus)
6759 {
6760 if (eHAL_STATUS_PMC_PENDING == halStatus)
6761 {
6762 /* request was sent -- wait for the response */
6763 lrc = wait_for_completion_interruptible_timeout(
6764 &powerContext.completion,
6765 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
6766 /* either we have a response or we timed out
6767 either way, first invalidate our magic */
6768 powerContext.magic = 0;
6769 if (lrc <= 0)
6770 {
6771 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006772 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07006773 /* there is a race condition such that the callback
6774 function could be executing at the same time we are. of
6775 primary concern is if the callback function had already
6776 verified the "magic" but hasn't yet set the completion
6777 variable. Since the completion variable is on our
6778 stack, we'll delay just a bit to make sure the data is
6779 still valid if that is the case */
6780 msleep(50);
6781 }
6782 }
6783 else
6784 {
6785 hddLog(VOS_TRACE_LEVEL_ERROR,
6786 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006787 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07006788 VOS_ASSERT(0);
6789 /* continue -- need to clean up as much as possible */
6790 }
6791 }
6792
Yue Ma0d4891e2013-08-06 17:01:45 -07006793 hdd_debugfs_exit(pHddCtx);
6794
Jeff Johnson295189b2012-06-20 16:38:30 -07006795 // Unregister the Net Device Notifier
6796 unregister_netdevice_notifier(&hdd_netdev_notifier);
6797
Jeff Johnson295189b2012-06-20 16:38:30 -07006798 hdd_stop_all_adapters( pHddCtx );
6799
Jeff Johnson295189b2012-06-20 16:38:30 -07006800#ifdef WLAN_BTAMP_FEATURE
6801 vosStatus = WLANBAP_Stop(pVosContext);
6802 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6803 {
6804 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
6805 "%s: Failed to stop BAP",__func__);
6806 }
6807#endif //WLAN_BTAMP_FEATURE
6808
6809 //Stop all the modules
6810 vosStatus = vos_stop( pVosContext );
6811 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6812 {
6813 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6814 "%s: Failed to stop VOSS",__func__);
6815 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6816 }
6817
Jeff Johnson295189b2012-06-20 16:38:30 -07006818 //Assert Deep sleep signal now to put Libra HW in lowest power state
6819 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6820 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6821
6822 //Vote off any PMIC voltage supplies
6823 vos_chipPowerDown(NULL, NULL, NULL);
6824
6825 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
6826
Leo Chang59cdc7e2013-07-10 10:08:21 -07006827
Jeff Johnson295189b2012-06-20 16:38:30 -07006828 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07006829 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006830
6831 //Close the scheduler before calling vos_close to make sure no thread is
6832 // scheduled after the each module close is called i.e after all the data
6833 // structures are freed.
6834 vosStatus = vos_sched_close( pVosContext );
6835 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
6836 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6837 "%s: Failed to close VOSS Scheduler",__func__);
6838 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6839 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006840#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006841#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6842 /* Destroy the wake lock */
6843 wake_lock_destroy(&pHddCtx->rx_wake_lock);
6844#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006845 /* Destroy the wake lock */
6846 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006847#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006848
6849 //Close VOSS
6850 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
6851 vos_close(pVosContext);
6852
Jeff Johnson295189b2012-06-20 16:38:30 -07006853 //Close Watchdog
6854 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6855 vos_watchdog_close(pVosContext);
6856
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306857 //Clean up HDD Nlink Service
6858 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07006859#ifdef WLAN_KD_READY_NOTIFIER
6860 nl_srv_exit(pHddCtx->ptt_pid);
6861#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306862 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006863#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306864
Jeff Johnson295189b2012-06-20 16:38:30 -07006865 /* Cancel the vote for XO Core ON.
6866 * This is done here to ensure there is no race condition since MC, TX and WD threads have
6867 * exited at this point
6868 */
6869 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
6870 " when WLAN is turned OFF\n");
6871 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6872 {
6873 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
6874 " Not returning failure."
6875 " Power consumed will be high\n");
6876 }
6877
6878 hdd_close_all_adapters( pHddCtx );
6879
6880
6881 //Free up dynamically allocated members inside HDD Adapter
6882 kfree(pHddCtx->cfg_ini);
6883 pHddCtx->cfg_ini= NULL;
6884
6885 /* free the power on lock from platform driver */
6886 if (free_riva_power_on_lock("wlan"))
6887 {
6888 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
6889 __func__);
6890 }
6891
Jeff Johnson88ba7742013-02-27 14:36:02 -08006892free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07006893 /* FTM mode, WIPHY did not registered
6894 If un-register here, system crash will happen */
6895 if (VOS_FTM_MODE != hdd_get_conparam())
6896 {
6897 wiphy_unregister(wiphy) ;
6898 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006899 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006900 if (hdd_is_ssr_required())
6901 {
6902 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07006903 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07006904 msleep(5000);
6905 }
6906 hdd_set_ssr_required (VOS_FALSE);
6907}
6908
6909
6910/**---------------------------------------------------------------------------
6911
6912 \brief hdd_update_config_from_nv() - Function to update the contents of
6913 the running configuration with parameters taken from NV storage
6914
6915 \param - pHddCtx - Pointer to the HDD global context
6916
6917 \return - VOS_STATUS_SUCCESS if successful
6918
6919 --------------------------------------------------------------------------*/
6920static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
6921{
Jeff Johnson295189b2012-06-20 16:38:30 -07006922 v_BOOL_t itemIsValid = VOS_FALSE;
6923 VOS_STATUS status;
6924 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
6925 v_U8_t macLoop;
6926
6927 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
6928 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
6929 if(status != VOS_STATUS_SUCCESS)
6930 {
6931 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
6932 return VOS_STATUS_E_FAILURE;
6933 }
6934
6935 if (itemIsValid == VOS_TRUE)
6936 {
6937 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
6938 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
6939 VOS_MAX_CONCURRENCY_PERSONA);
6940 if(status != VOS_STATUS_SUCCESS)
6941 {
6942 /* Get MAC from NV fail, not update CFG info
6943 * INI MAC value will be used for MAC setting */
6944 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
6945 return VOS_STATUS_E_FAILURE;
6946 }
6947
6948 /* If first MAC is not valid, treat all others are not valid
6949 * Then all MACs will be got from ini file */
6950 if(vos_is_macaddr_zero(&macFromNV[0]))
6951 {
6952 /* MAC address in NV file is not configured yet */
6953 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
6954 return VOS_STATUS_E_INVAL;
6955 }
6956
6957 /* Get MAC address from NV, update CFG info */
6958 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
6959 {
6960 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
6961 {
6962 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
6963 /* This MAC is not valid, skip it
6964 * This MAC will be got from ini file */
6965 }
6966 else
6967 {
6968 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
6969 (v_U8_t *)&macFromNV[macLoop].bytes[0],
6970 VOS_MAC_ADDR_SIZE);
6971 }
6972 }
6973 }
6974 else
6975 {
6976 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
6977 return VOS_STATUS_E_FAILURE;
6978 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006979
Jeff Johnson295189b2012-06-20 16:38:30 -07006980
6981 return VOS_STATUS_SUCCESS;
6982}
6983
6984/**---------------------------------------------------------------------------
6985
6986 \brief hdd_post_voss_start_config() - HDD post voss start config helper
6987
6988 \param - pAdapter - Pointer to the HDD
6989
6990 \return - None
6991
6992 --------------------------------------------------------------------------*/
6993VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
6994{
6995 eHalStatus halStatus;
6996 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306997 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07006998
Jeff Johnson295189b2012-06-20 16:38:30 -07006999
7000 // Send ready indication to the HDD. This will kick off the MAC
7001 // into a 'running' state and should kick off an initial scan.
7002 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7003 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7004 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307005 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007006 "code %08d [x%08x]",__func__, halStatus, halStatus );
7007 return VOS_STATUS_E_FAILURE;
7008 }
7009
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307010 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007011 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7012 // And RIVA will crash
7013 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7014 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307015 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7016 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7017
7018
Jeff Johnson295189b2012-06-20 16:38:30 -07007019 return VOS_STATUS_SUCCESS;
7020}
7021
Jeff Johnson295189b2012-06-20 16:38:30 -07007022/* wake lock APIs for HDD */
7023void hdd_prevent_suspend(void)
7024{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007025#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007026 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007027#else
7028 wcnss_prevent_suspend();
7029#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007030}
7031
7032void hdd_allow_suspend(void)
7033{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007034#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007035 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007036#else
7037 wcnss_allow_suspend();
7038#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007039}
7040
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007041void hdd_allow_suspend_timeout(v_U32_t timeout)
7042{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007043#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007044 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007045#else
7046 /* Do nothing as there is no API in wcnss for timeout*/
7047#endif
7048}
7049
Jeff Johnson295189b2012-06-20 16:38:30 -07007050/**---------------------------------------------------------------------------
7051
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007052 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7053 information between Host and Riva
7054
7055 This function gets reported version of FW
7056 It also finds the version of Riva headers used to compile the host
7057 It compares the above two and prints a warning if they are different
7058 It gets the SW and HW version string
7059 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7060 indicating the features they support through a bitmap
7061
7062 \param - pHddCtx - Pointer to HDD context
7063
7064 \return - void
7065
7066 --------------------------------------------------------------------------*/
7067
7068void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7069{
7070
7071 tSirVersionType versionCompiled;
7072 tSirVersionType versionReported;
7073 tSirVersionString versionString;
7074 tANI_U8 fwFeatCapsMsgSupported = 0;
7075 VOS_STATUS vstatus;
7076
7077 /* retrieve and display WCNSS version information */
7078 do {
7079
7080 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7081 &versionCompiled);
7082 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7083 {
7084 hddLog(VOS_TRACE_LEVEL_FATAL,
7085 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007086 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007087 break;
7088 }
7089
7090 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7091 &versionReported);
7092 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7093 {
7094 hddLog(VOS_TRACE_LEVEL_FATAL,
7095 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007096 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007097 break;
7098 }
7099
7100 if ((versionCompiled.major != versionReported.major) ||
7101 (versionCompiled.minor != versionReported.minor) ||
7102 (versionCompiled.version != versionReported.version) ||
7103 (versionCompiled.revision != versionReported.revision))
7104 {
7105 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7106 "Host expected %u.%u.%u.%u\n",
7107 WLAN_MODULE_NAME,
7108 (int)versionReported.major,
7109 (int)versionReported.minor,
7110 (int)versionReported.version,
7111 (int)versionReported.revision,
7112 (int)versionCompiled.major,
7113 (int)versionCompiled.minor,
7114 (int)versionCompiled.version,
7115 (int)versionCompiled.revision);
7116 }
7117 else
7118 {
7119 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7120 WLAN_MODULE_NAME,
7121 (int)versionReported.major,
7122 (int)versionReported.minor,
7123 (int)versionReported.version,
7124 (int)versionReported.revision);
7125 }
7126
7127 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7128 versionString,
7129 sizeof(versionString));
7130 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7131 {
7132 hddLog(VOS_TRACE_LEVEL_FATAL,
7133 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007134 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007135 break;
7136 }
7137
7138 pr_info("%s: WCNSS software version %s\n",
7139 WLAN_MODULE_NAME, versionString);
7140
7141 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7142 versionString,
7143 sizeof(versionString));
7144 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7145 {
7146 hddLog(VOS_TRACE_LEVEL_FATAL,
7147 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007148 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007149 break;
7150 }
7151
7152 pr_info("%s: WCNSS hardware version %s\n",
7153 WLAN_MODULE_NAME, versionString);
7154
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007155 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7156 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007157 send the message only if it the riva is 1.1
7158 minor numbers for different riva branches:
7159 0 -> (1.0)Mainline Build
7160 1 -> (1.1)Mainline Build
7161 2->(1.04) Stability Build
7162 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007163 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007164 ((versionReported.minor>=1) && (versionReported.version>=1)))
7165 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7166 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007167
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007168 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007169 {
7170#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7171 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7172 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7173#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007174 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7175 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7176 {
7177 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7178 }
7179
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007180 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007181 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007182
7183 } while (0);
7184
7185}
7186
7187/**---------------------------------------------------------------------------
7188
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307189 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7190
7191 \param - pHddCtx - Pointer to the hdd context
7192
7193 \return - true if hardware supports 5GHz
7194
7195 --------------------------------------------------------------------------*/
7196static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7197{
7198 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7199 * then hardware support 5Ghz.
7200 */
7201 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7202 {
7203 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7204 return true;
7205 }
7206 else
7207 {
7208 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7209 __func__);
7210 return false;
7211 }
7212}
7213
7214
7215/**---------------------------------------------------------------------------
7216
Jeff Johnson295189b2012-06-20 16:38:30 -07007217 \brief hdd_wlan_startup() - HDD init function
7218
7219 This is the driver startup code executed once a WLAN device has been detected
7220
7221 \param - dev - Pointer to the underlying device
7222
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007223 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007224
7225 --------------------------------------------------------------------------*/
7226
7227int hdd_wlan_startup(struct device *dev )
7228{
7229 VOS_STATUS status;
7230 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007231 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007232 hdd_context_t *pHddCtx = NULL;
7233 v_CONTEXT_t pVosContext= NULL;
7234#ifdef WLAN_BTAMP_FEATURE
7235 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7236 WLANBAP_ConfigType btAmpConfig;
7237 hdd_config_t *pConfig;
7238#endif
7239 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007240 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007241
7242 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007243 /*
7244 * cfg80211: wiphy allocation
7245 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307246 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007247
7248 if(wiphy == NULL)
7249 {
7250 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007251 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007252 }
7253
7254 pHddCtx = wiphy_priv(wiphy);
7255
Jeff Johnson295189b2012-06-20 16:38:30 -07007256 //Initialize the adapter context to zeros.
7257 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7258
Jeff Johnson295189b2012-06-20 16:38:30 -07007259 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007260 hdd_prevent_suspend();
7261 pHddCtx->isLoadUnloadInProgress = TRUE;
7262
7263 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7264
7265 /*Get vos context here bcoz vos_open requires it*/
7266 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7267
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007268 if(pVosContext == NULL)
7269 {
7270 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7271 goto err_free_hdd_context;
7272 }
7273
Jeff Johnson295189b2012-06-20 16:38:30 -07007274 //Save the Global VOSS context in adapter context for future.
7275 pHddCtx->pvosContext = pVosContext;
7276
7277 //Save the adapter context in global context for future.
7278 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7279
Jeff Johnson295189b2012-06-20 16:38:30 -07007280 pHddCtx->parent_dev = dev;
7281
7282 init_completion(&pHddCtx->full_pwr_comp_var);
7283 init_completion(&pHddCtx->standby_comp_var);
7284 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007285 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007286 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07007287
7288#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007289 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007290#else
7291 init_completion(&pHddCtx->driver_crda_req);
7292#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007293
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307294 spin_lock_init(&pHddCtx->schedScan_lock);
7295
Jeff Johnson295189b2012-06-20 16:38:30 -07007296 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7297
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307298#ifdef FEATURE_WLAN_TDLS
7299 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7300 * invoked by other instances also) to protect the concurrent
7301 * access for the Adapters by TDLS module.
7302 */
7303 mutex_init(&pHddCtx->tdls_lock);
7304#endif
7305
Jeff Johnson295189b2012-06-20 16:38:30 -07007306 // Load all config first as TL config is needed during vos_open
7307 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7308 if(pHddCtx->cfg_ini == NULL)
7309 {
7310 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7311 goto err_free_hdd_context;
7312 }
7313
7314 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7315
7316 // Read and parse the qcom_cfg.ini file
7317 status = hdd_parse_config_ini( pHddCtx );
7318 if ( VOS_STATUS_SUCCESS != status )
7319 {
7320 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7321 __func__, WLAN_INI_FILE);
7322 goto err_config;
7323 }
7324
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307325 /* INI has been read, initialise the configuredMcastBcastFilter with
7326 * INI value as this will serve as the default value
7327 */
7328 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7329 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7330 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307331
7332 if (false == hdd_is_5g_supported(pHddCtx))
7333 {
7334 //5Ghz is not supported.
7335 if (1 != pHddCtx->cfg_ini->nBandCapability)
7336 {
7337 hddLog(VOS_TRACE_LEVEL_INFO,
7338 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7339 pHddCtx->cfg_ini->nBandCapability = 1;
7340 }
7341 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307342
7343 /* If SNR Monitoring is enabled, FW has to parse all beacons
7344 * for calcaluting and storing the average SNR, so set Nth beacon
7345 * filter to 1 to enable FW to parse all the beaocons
7346 */
7347 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7348 {
7349 /* The log level is deliberately set to WARN as overriding
7350 * nthBeaconFilter to 1 will increase power cosumption and this
7351 * might just prove helpful to detect the power issue.
7352 */
7353 hddLog(VOS_TRACE_LEVEL_WARN,
7354 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7355 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7356 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007357 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307358 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007359 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307360 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007361 {
7362 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307363 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7364 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007365 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007366
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007367 // Update VOS trace levels based upon the cfg.ini
7368 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7369 pHddCtx->cfg_ini->vosTraceEnableBAP);
7370 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7371 pHddCtx->cfg_ini->vosTraceEnableTL);
7372 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7373 pHddCtx->cfg_ini->vosTraceEnableWDI);
7374 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7375 pHddCtx->cfg_ini->vosTraceEnableHDD);
7376 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7377 pHddCtx->cfg_ini->vosTraceEnableSME);
7378 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7379 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307380 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7381 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007382 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7383 pHddCtx->cfg_ini->vosTraceEnableWDA);
7384 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7385 pHddCtx->cfg_ini->vosTraceEnableSYS);
7386 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7387 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007388 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7389 pHddCtx->cfg_ini->vosTraceEnableSAP);
7390 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7391 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007392
Jeff Johnson295189b2012-06-20 16:38:30 -07007393 // Update WDI trace levels based upon the cfg.ini
7394 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7395 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7396 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7397 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7398 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7399 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7400 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7401 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007402
Jeff Johnson88ba7742013-02-27 14:36:02 -08007403 if (VOS_FTM_MODE == hdd_get_conparam())
7404 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007405 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7406 {
7407 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7408 goto err_free_hdd_context;
7409 }
7410 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7411 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007412 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007413
Jeff Johnson88ba7742013-02-27 14:36:02 -08007414 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007415 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7416 {
7417 status = vos_watchdog_open(pVosContext,
7418 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7419
7420 if(!VOS_IS_STATUS_SUCCESS( status ))
7421 {
7422 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307423 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007424 }
7425 }
7426
7427 pHddCtx->isLogpInProgress = FALSE;
7428 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7429
Jeff Johnson295189b2012-06-20 16:38:30 -07007430 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7431 if(!VOS_IS_STATUS_SUCCESS(status))
7432 {
7433 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007434 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007435 }
7436
Amar Singhala49cbc52013-10-08 18:37:44 -07007437#ifdef CONFIG_ENABLE_LINUX_REG
7438 /* registration of wiphy dev with cfg80211 */
7439 if (0 > wlan_hdd_cfg80211_register(wiphy))
7440 {
7441 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7442 goto err_clkvote;
7443 }
7444#endif
7445
Jeff Johnson295189b2012-06-20 16:38:30 -07007446 status = vos_open( &pVosContext, 0);
7447 if ( !VOS_IS_STATUS_SUCCESS( status ))
7448 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007449 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007450 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007451 }
7452
Jeff Johnson295189b2012-06-20 16:38:30 -07007453 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7454
7455 if ( NULL == pHddCtx->hHal )
7456 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007457 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007458 goto err_vosclose;
7459 }
7460
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007461 status = vos_preStart( pHddCtx->pvosContext );
7462 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7463 {
7464 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7465 goto err_vosclose;
7466 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007467
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007468 /* Note that the vos_preStart() sequence triggers the cfg download.
7469 The cfg download must occur before we update the SME config
7470 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007471 status = hdd_set_sme_config( pHddCtx );
7472
7473 if ( VOS_STATUS_SUCCESS != status )
7474 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007475 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7476 goto err_vosclose;
7477 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007478
7479 //Initialize the WMM module
7480 status = hdd_wmm_init(pHddCtx);
7481 if (!VOS_IS_STATUS_SUCCESS(status))
7482 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007483 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007484 goto err_vosclose;
7485 }
7486
Jeff Johnson295189b2012-06-20 16:38:30 -07007487 /* In the integrated architecture we update the configuration from
7488 the INI file and from NV before vOSS has been started so that
7489 the final contents are available to send down to the cCPU */
7490
7491 // Apply the cfg.ini to cfg.dat
7492 if (FALSE == hdd_update_config_dat(pHddCtx))
7493 {
7494 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7495 goto err_vosclose;
7496 }
7497
7498 // Apply the NV to cfg.dat
7499 /* Prima Update MAC address only at here */
7500 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7501 {
7502#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7503 /* There was not a valid set of MAC Addresses in NV. See if the
7504 default addresses were modified by the cfg.ini settings. If so,
7505 we'll use them, but if not, we'll autogenerate a set of MAC
7506 addresses based upon the device serial number */
7507
7508 static const v_MACADDR_t default_address =
7509 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7510 unsigned int serialno;
7511 int i;
7512
7513 serialno = wcnss_get_serial_number();
7514 if ((0 != serialno) &&
7515 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7516 sizeof(default_address))))
7517 {
7518 /* cfg.ini has the default address, invoke autogen logic */
7519
7520 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7521 bytes of the serial number that can be used to generate
7522 the other 3 bytes of the MAC address. Mask off all but
7523 the lower 3 bytes (this will also make sure we don't
7524 overflow in the next step) */
7525 serialno &= 0x00FFFFFF;
7526
7527 /* we need a unique address for each session */
7528 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7529
7530 /* autogen all addresses */
7531 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7532 {
7533 /* start with the entire default address */
7534 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7535 /* then replace the lower 3 bytes */
7536 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7537 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7538 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7539
7540 serialno++;
7541 }
7542
7543 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7544 MAC_ADDRESS_STR,
7545 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7546 }
7547 else
7548#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7549 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007550 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007551 "%s: Invalid MAC address in NV, using MAC from ini file "
7552 MAC_ADDRESS_STR, __func__,
7553 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7554 }
7555 }
7556 {
7557 eHalStatus halStatus;
7558 // Set the MAC Address
7559 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7560 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7561 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7562 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7563
7564 if (!HAL_STATUS_SUCCESS( halStatus ))
7565 {
7566 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7567 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007568 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007569 }
7570 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007571
7572 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7573 Note: Firmware image will be read and downloaded inside vos_start API */
7574 status = vos_start( pHddCtx->pvosContext );
7575 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7576 {
7577 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7578 goto err_vosclose;
7579 }
7580
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007581 /* Exchange capability info between Host and FW and also get versioning info from FW */
7582 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007583
7584 status = hdd_post_voss_start_config( pHddCtx );
7585 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7586 {
7587 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7588 __func__);
7589 goto err_vosstop;
7590 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007591
7592#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307593 wlan_hdd_cfg80211_update_reg_info( wiphy );
7594
7595 /* registration of wiphy dev with cfg80211 */
7596 if (0 > wlan_hdd_cfg80211_register(wiphy))
7597 {
7598 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7599 goto err_vosstop;
7600 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007601#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007602
Jeff Johnson295189b2012-06-20 16:38:30 -07007603 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7604 {
7605 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7606 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7607 }
7608 else
7609 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007610 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7611 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7612 if (pAdapter != NULL)
7613 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307614 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007615 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307616 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7617 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7618 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007619
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307620 /* Generate the P2P Device Address. This consists of the device's
7621 * primary MAC address with the locally administered bit set.
7622 */
7623 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007624 }
7625 else
7626 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307627 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7628 if (p2p_dev_addr != NULL)
7629 {
7630 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7631 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7632 }
7633 else
7634 {
7635 hddLog(VOS_TRACE_LEVEL_FATAL,
7636 "%s: Failed to allocate mac_address for p2p_device",
7637 __func__);
7638 goto err_close_adapter;
7639 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007640 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007641
7642 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7643 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7644 if ( NULL == pP2pAdapter )
7645 {
7646 hddLog(VOS_TRACE_LEVEL_FATAL,
7647 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007648 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007649 goto err_close_adapter;
7650 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007651 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007652 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007653
7654 if( pAdapter == NULL )
7655 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007656 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7657 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007658 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007659
Jeff Johnson295189b2012-06-20 16:38:30 -07007660#ifdef WLAN_BTAMP_FEATURE
7661 vStatus = WLANBAP_Open(pVosContext);
7662 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7663 {
7664 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7665 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007666 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007667 }
7668
7669 vStatus = BSL_Init(pVosContext);
7670 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7671 {
7672 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7673 "%s: Failed to Init BSL",__func__);
7674 goto err_bap_close;
7675 }
7676 vStatus = WLANBAP_Start(pVosContext);
7677 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7678 {
7679 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7680 "%s: Failed to start TL",__func__);
7681 goto err_bap_close;
7682 }
7683
7684 pConfig = pHddCtx->cfg_ini;
7685 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7686 status = WLANBAP_SetConfig(&btAmpConfig);
7687
7688#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007689
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007690#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7691 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7692 {
7693 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7694 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7695 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7696 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7697 }
7698#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007699#ifdef FEATURE_WLAN_SCAN_PNO
7700 /*SME must send channel update configuration to RIVA*/
7701 sme_UpdateChannelConfig(pHddCtx->hHal);
7702#endif
7703
Jeff Johnson295189b2012-06-20 16:38:30 -07007704 /* Register with platform driver as client for Suspend/Resume */
7705 status = hddRegisterPmOps(pHddCtx);
7706 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7707 {
7708 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7709#ifdef WLAN_BTAMP_FEATURE
7710 goto err_bap_stop;
7711#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007712 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007713#endif //WLAN_BTAMP_FEATURE
7714 }
7715
Yue Ma0d4891e2013-08-06 17:01:45 -07007716 /* Open debugfs interface */
7717 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
7718 {
7719 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7720 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07007721 }
7722
Jeff Johnson295189b2012-06-20 16:38:30 -07007723 /* Register TM level change handler function to the platform */
7724 status = hddDevTmRegisterNotifyCallback(pHddCtx);
7725 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7726 {
7727 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
7728 goto err_unregister_pmops;
7729 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007730
7731 /* register for riva power on lock to platform driver */
7732 if (req_riva_power_on_lock("wlan"))
7733 {
7734 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
7735 __func__);
7736 goto err_unregister_pmops;
7737 }
7738
Jeff Johnson295189b2012-06-20 16:38:30 -07007739 // register net device notifier for device change notification
7740 ret = register_netdevice_notifier(&hdd_netdev_notifier);
7741
7742 if(ret < 0)
7743 {
7744 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
7745 goto err_free_power_on_lock;
7746 }
7747
7748 //Initialize the nlink service
7749 if(nl_srv_init() != 0)
7750 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307751 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007752 goto err_reg_netdev;
7753 }
7754
Leo Chang4ce1cc52013-10-21 18:27:15 -07007755#ifdef WLAN_KD_READY_NOTIFIER
7756 pHddCtx->kd_nl_init = 1;
7757#endif /* WLAN_KD_READY_NOTIFIER */
7758
Jeff Johnson295189b2012-06-20 16:38:30 -07007759 //Initialize the BTC service
7760 if(btc_activate_service(pHddCtx) != 0)
7761 {
7762 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
7763 goto err_nl_srv;
7764 }
7765
7766#ifdef PTT_SOCK_SVC_ENABLE
7767 //Initialize the PTT service
7768 if(ptt_sock_activate_svc(pHddCtx) != 0)
7769 {
7770 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
7771 goto err_nl_srv;
7772 }
7773#endif
7774
Jeff Johnson295189b2012-06-20 16:38:30 -07007775 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007776 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007777 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07007778 /* Action frame registered in one adapter which will
7779 * applicable to all interfaces
7780 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07007781 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007782 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007783
7784 mutex_init(&pHddCtx->sap_lock);
7785
7786 pHddCtx->isLoadUnloadInProgress = FALSE;
7787
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007788#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007789#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7790 /* Initialize the wake lcok */
7791 wake_lock_init(&pHddCtx->rx_wake_lock,
7792 WAKE_LOCK_SUSPEND,
7793 "qcom_rx_wakelock");
7794#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007795 /* Initialize the wake lcok */
7796 wake_lock_init(&pHddCtx->sap_wake_lock,
7797 WAKE_LOCK_SUSPEND,
7798 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007799#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007800
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007801 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
7802 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07007803
7804 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7805 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05307806
Jeff Johnsone7245742012-09-05 17:12:55 -07007807 // Initialize the restart logic
7808 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05307809
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007810 //Register the traffic monitor timer now
7811 if ( pHddCtx->cfg_ini->dynSplitscan)
7812 {
7813 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
7814 VOS_TIMER_TYPE_SW,
7815 hdd_tx_rx_pkt_cnt_stat_timer_handler,
7816 (void *)pHddCtx);
7817 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007818 goto success;
7819
7820err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07007821#ifdef WLAN_KD_READY_NOTIFIER
7822 nl_srv_exit(pHddCtx->ptt_pid);
7823#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007824 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007825#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07007826err_reg_netdev:
7827 unregister_netdevice_notifier(&hdd_netdev_notifier);
7828
7829err_free_power_on_lock:
7830 free_riva_power_on_lock("wlan");
7831
7832err_unregister_pmops:
7833 hddDevTmUnregisterNotifyCallback(pHddCtx);
7834 hddDeregisterPmOps(pHddCtx);
7835
Yue Ma0d4891e2013-08-06 17:01:45 -07007836 hdd_debugfs_exit(pHddCtx);
7837
Jeff Johnson295189b2012-06-20 16:38:30 -07007838#ifdef WLAN_BTAMP_FEATURE
7839err_bap_stop:
7840 WLANBAP_Stop(pVosContext);
7841#endif
7842
7843#ifdef WLAN_BTAMP_FEATURE
7844err_bap_close:
7845 WLANBAP_Close(pVosContext);
7846#endif
7847
Jeff Johnson295189b2012-06-20 16:38:30 -07007848err_close_adapter:
7849 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07007850
7851#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307852 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07007853#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007854
7855err_vosstop:
7856 vos_stop(pVosContext);
7857
Amar Singhala49cbc52013-10-08 18:37:44 -07007858err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07007859 status = vos_sched_close( pVosContext );
7860 if (!VOS_IS_STATUS_SUCCESS(status)) {
7861 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7862 "%s: Failed to close VOSS Scheduler", __func__);
7863 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
7864 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007865 vos_close(pVosContext );
7866
7867err_wiphy_unregister:
7868
7869#ifdef CONFIG_ENABLE_LINUX_REG
7870 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07007871
Jeff Johnson295189b2012-06-20 16:38:30 -07007872err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07007873#endif
7874
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007875 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007876
7877err_wdclose:
7878 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7879 vos_watchdog_close(pVosContext);
7880
Jeff Johnson295189b2012-06-20 16:38:30 -07007881err_config:
7882 kfree(pHddCtx->cfg_ini);
7883 pHddCtx->cfg_ini= NULL;
7884
7885err_free_hdd_context:
7886 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07007887 wiphy_free(wiphy) ;
7888 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007889 VOS_BUG(1);
7890
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08007891 if (hdd_is_ssr_required())
7892 {
7893 /* WDI timeout had happened during load, so SSR is needed here */
7894 subsystem_restart("wcnss");
7895 msleep(5000);
7896 }
7897 hdd_set_ssr_required (VOS_FALSE);
7898
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007899 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007900
7901success:
7902 EXIT();
7903 return 0;
7904}
7905
7906/**---------------------------------------------------------------------------
7907
Jeff Johnson32d95a32012-09-10 13:15:23 -07007908 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07007909
Jeff Johnson32d95a32012-09-10 13:15:23 -07007910 This is the driver entry point - called in different timeline depending
7911 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07007912
7913 \param - None
7914
7915 \return - 0 for success, non zero for failure
7916
7917 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07007918static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007919{
7920 VOS_STATUS status;
7921 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007922 struct device *dev = NULL;
7923 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007924#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7925 int max_retries = 0;
7926#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007927
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307928#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7929 vos_wconn_trace_init();
7930#endif
7931
Jeff Johnson295189b2012-06-20 16:38:30 -07007932 ENTER();
7933
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007934#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007935 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07007936#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007937
7938 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
7939 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
7940
7941 //Power Up Libra WLAN card first if not already powered up
7942 status = vos_chipPowerUp(NULL,NULL,NULL);
7943 if (!VOS_IS_STATUS_SUCCESS(status))
7944 {
7945 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
7946 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307947#ifdef WLAN_OPEN_SOURCE
7948 wake_lock_destroy(&wlan_wake_lock);
7949#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007950 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007951 }
7952
Jeff Johnson295189b2012-06-20 16:38:30 -07007953#ifdef ANI_BUS_TYPE_PCI
7954
7955 dev = wcnss_wlan_get_device();
7956
7957#endif // ANI_BUS_TYPE_PCI
7958
7959#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007960
7961#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7962 /* wait until WCNSS driver downloads NV */
7963 while (!wcnss_device_ready() && 5 >= ++max_retries) {
7964 msleep(1000);
7965 }
7966 if (max_retries >= 5) {
7967 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307968#ifdef WLAN_OPEN_SOURCE
7969 wake_lock_destroy(&wlan_wake_lock);
7970#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007971 return -ENODEV;
7972 }
7973#endif
7974
Jeff Johnson295189b2012-06-20 16:38:30 -07007975 dev = wcnss_wlan_get_device();
7976#endif // ANI_BUS_TYPE_PLATFORM
7977
7978
7979 do {
7980 if (NULL == dev) {
7981 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
7982 ret_status = -1;
7983 break;
7984 }
7985
7986#ifdef MEMORY_DEBUG
7987 vos_mem_init();
7988#endif
7989
7990#ifdef TIMER_MANAGER
7991 vos_timer_manager_init();
7992#endif
7993
7994 /* Preopen VOSS so that it is ready to start at least SAL */
7995 status = vos_preOpen(&pVosContext);
7996
7997 if (!VOS_IS_STATUS_SUCCESS(status))
7998 {
7999 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8000 ret_status = -1;
8001 break;
8002 }
8003
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008004#ifndef MODULE
8005 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8006 */
8007 hdd_set_conparam((v_UINT_t)con_mode);
8008#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008009
8010 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008011 if (hdd_wlan_startup(dev))
8012 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008013 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008014 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008015 vos_preClose( &pVosContext );
8016 ret_status = -1;
8017 break;
8018 }
8019
8020 /* Cancel the vote for XO Core ON
8021 * This is done here for safety purposes in case we re-initialize without turning
8022 * it OFF in any error scenario.
8023 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008024 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008025 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008026 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008027 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8028 {
8029 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
8030 " Power consumed will be high\n");
8031 }
8032 } while (0);
8033
8034 if (0 != ret_status)
8035 {
8036 //Assert Deep sleep signal now to put Libra HW in lowest power state
8037 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8038 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8039
8040 //Vote off any PMIC voltage supplies
8041 vos_chipPowerDown(NULL, NULL, NULL);
8042#ifdef TIMER_MANAGER
8043 vos_timer_exit();
8044#endif
8045#ifdef MEMORY_DEBUG
8046 vos_mem_exit();
8047#endif
8048
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008049#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008050 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008051#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008052 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8053 }
8054 else
8055 {
8056 //Send WLAN UP indication to Nlink Service
8057 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8058
8059 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008060 }
8061
8062 EXIT();
8063
8064 return ret_status;
8065}
8066
Jeff Johnson32d95a32012-09-10 13:15:23 -07008067/**---------------------------------------------------------------------------
8068
8069 \brief hdd_module_init() - Init Function
8070
8071 This is the driver entry point (invoked when module is loaded using insmod)
8072
8073 \param - None
8074
8075 \return - 0 for success, non zero for failure
8076
8077 --------------------------------------------------------------------------*/
8078#ifdef MODULE
8079static int __init hdd_module_init ( void)
8080{
8081 return hdd_driver_init();
8082}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008083#else /* #ifdef MODULE */
8084static int __init hdd_module_init ( void)
8085{
8086 /* Driver initialization is delayed to fwpath_changed_handler */
8087 return 0;
8088}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008089#endif /* #ifdef MODULE */
8090
Jeff Johnson295189b2012-06-20 16:38:30 -07008091
8092/**---------------------------------------------------------------------------
8093
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008094 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008095
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008096 This is the driver exit point (invoked when module is unloaded using rmmod
8097 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008098
8099 \param - None
8100
8101 \return - None
8102
8103 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008104static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008105{
8106 hdd_context_t *pHddCtx = NULL;
8107 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008108 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008109
8110 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8111
8112 //Get the global vos context
8113 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8114
8115 if(!pVosContext)
8116 {
8117 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8118 goto done;
8119 }
8120
8121 //Get the HDD context.
8122 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8123
8124 if(!pHddCtx)
8125 {
8126 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8127 }
8128 else
8129 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008130 while(isWDresetInProgress()) {
8131 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8132 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008133 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008134
8135 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8136 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8137 "%s:SSR never completed, fatal error", __func__);
8138 VOS_BUG(0);
8139 }
8140 }
8141
Jeff Johnson295189b2012-06-20 16:38:30 -07008142
8143 pHddCtx->isLoadUnloadInProgress = TRUE;
8144 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8145
8146 //Do all the cleanup before deregistering the driver
8147 hdd_wlan_exit(pHddCtx);
8148 }
8149
Jeff Johnson295189b2012-06-20 16:38:30 -07008150 vos_preClose( &pVosContext );
8151
8152#ifdef TIMER_MANAGER
8153 vos_timer_exit();
8154#endif
8155#ifdef MEMORY_DEBUG
8156 vos_mem_exit();
8157#endif
8158
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308159#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8160 vos_wconn_trace_exit();
8161#endif
8162
Jeff Johnson295189b2012-06-20 16:38:30 -07008163done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008164#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008165 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008166#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008167 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8168}
8169
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008170/**---------------------------------------------------------------------------
8171
8172 \brief hdd_module_exit() - Exit function
8173
8174 This is the driver exit point (invoked when module is unloaded using rmmod)
8175
8176 \param - None
8177
8178 \return - None
8179
8180 --------------------------------------------------------------------------*/
8181static void __exit hdd_module_exit(void)
8182{
8183 hdd_driver_exit();
8184}
8185
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008186#ifdef MODULE
8187static int fwpath_changed_handler(const char *kmessage,
8188 struct kernel_param *kp)
8189{
Jeff Johnson76052702013-04-16 13:55:05 -07008190 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008191}
8192
8193static int con_mode_handler(const char *kmessage,
8194 struct kernel_param *kp)
8195{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008196 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008197}
8198#else /* #ifdef MODULE */
8199/**---------------------------------------------------------------------------
8200
Jeff Johnson76052702013-04-16 13:55:05 -07008201 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008202
Jeff Johnson76052702013-04-16 13:55:05 -07008203 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008204 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008205 - invoked when module parameter fwpath is modified from userspace to signal
8206 initializing the WLAN driver or when con_mode is modified from userspace
8207 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008208
8209 \return - 0 for success, non zero for failure
8210
8211 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008212static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008213{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008214 int ret_status;
8215
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008216 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008217 ret_status = hdd_driver_init();
8218 wlan_hdd_inited = ret_status ? 0 : 1;
8219 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008220 }
8221
8222 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008223
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008224 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008225
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008226 ret_status = hdd_driver_init();
8227 wlan_hdd_inited = ret_status ? 0 : 1;
8228 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008229}
8230
Jeff Johnson295189b2012-06-20 16:38:30 -07008231/**---------------------------------------------------------------------------
8232
Jeff Johnson76052702013-04-16 13:55:05 -07008233 \brief fwpath_changed_handler() - Handler Function
8234
8235 Handle changes to the fwpath parameter
8236
8237 \return - 0 for success, non zero for failure
8238
8239 --------------------------------------------------------------------------*/
8240static int fwpath_changed_handler(const char *kmessage,
8241 struct kernel_param *kp)
8242{
8243 int ret;
8244
8245 ret = param_set_copystring(kmessage, kp);
8246 if (0 == ret)
8247 ret = kickstart_driver();
8248 return ret;
8249}
8250
8251/**---------------------------------------------------------------------------
8252
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008253 \brief con_mode_handler() -
8254
8255 Handler function for module param con_mode when it is changed by userspace
8256 Dynamically linked - do nothing
8257 Statically linked - exit and init driver, as in rmmod and insmod
8258
Jeff Johnson76052702013-04-16 13:55:05 -07008259 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008260
Jeff Johnson76052702013-04-16 13:55:05 -07008261 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008262
8263 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008264static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008265{
Jeff Johnson76052702013-04-16 13:55:05 -07008266 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008267
Jeff Johnson76052702013-04-16 13:55:05 -07008268 ret = param_set_int(kmessage, kp);
8269 if (0 == ret)
8270 ret = kickstart_driver();
8271 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008272}
8273#endif /* #ifdef MODULE */
8274
8275/**---------------------------------------------------------------------------
8276
Jeff Johnson295189b2012-06-20 16:38:30 -07008277 \brief hdd_get_conparam() -
8278
8279 This is the driver exit point (invoked when module is unloaded using rmmod)
8280
8281 \param - None
8282
8283 \return - tVOS_CON_MODE
8284
8285 --------------------------------------------------------------------------*/
8286tVOS_CON_MODE hdd_get_conparam ( void )
8287{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008288#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008289 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008290#else
8291 return (tVOS_CON_MODE)curr_con_mode;
8292#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008293}
8294void hdd_set_conparam ( v_UINT_t newParam )
8295{
8296 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008297#ifndef MODULE
8298 curr_con_mode = con_mode;
8299#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008300}
8301/**---------------------------------------------------------------------------
8302
8303 \brief hdd_softap_sta_deauth() - function
8304
8305 This to take counter measure to handle deauth req from HDD
8306
8307 \param - pAdapter - Pointer to the HDD
8308
8309 \param - enable - boolean value
8310
8311 \return - None
8312
8313 --------------------------------------------------------------------------*/
8314
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008315VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008316{
Jeff Johnson295189b2012-06-20 16:38:30 -07008317 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008318 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008319
8320 ENTER();
8321
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008322 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8323 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008324
8325 //Ignore request to deauth bcmc station
8326 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008327 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008328
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008329 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008330
8331 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008332 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008333}
8334
8335/**---------------------------------------------------------------------------
8336
8337 \brief hdd_softap_sta_disassoc() - function
8338
8339 This to take counter measure to handle deauth req from HDD
8340
8341 \param - pAdapter - Pointer to the HDD
8342
8343 \param - enable - boolean value
8344
8345 \return - None
8346
8347 --------------------------------------------------------------------------*/
8348
8349void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8350{
8351 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8352
8353 ENTER();
8354
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308355 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008356
8357 //Ignore request to disassoc bcmc station
8358 if( pDestMacAddress[0] & 0x1 )
8359 return;
8360
8361 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8362}
8363
8364void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8365{
8366 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8367
8368 ENTER();
8369
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308370 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008371
8372 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8373}
8374
Jeff Johnson295189b2012-06-20 16:38:30 -07008375/**---------------------------------------------------------------------------
8376 *
8377 * \brief hdd_get__concurrency_mode() -
8378 *
8379 *
8380 * \param - None
8381 *
8382 * \return - CONCURRENCY MODE
8383 *
8384 * --------------------------------------------------------------------------*/
8385tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8386{
8387 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8388 hdd_context_t *pHddCtx;
8389
8390 if (NULL != pVosContext)
8391 {
8392 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8393 if (NULL != pHddCtx)
8394 {
8395 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8396 }
8397 }
8398
8399 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008400 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008401 return VOS_STA;
8402}
8403
8404/* Decide whether to allow/not the apps power collapse.
8405 * Allow apps power collapse if we are in connected state.
8406 * if not, allow only if we are in IMPS */
8407v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8408{
8409 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008410 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008411 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008412 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8413 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8414 hdd_adapter_t *pAdapter = NULL;
8415 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008416 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008417
Jeff Johnson295189b2012-06-20 16:38:30 -07008418 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8419 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008420
Yathish9f22e662012-12-10 14:21:35 -08008421 concurrent_state = hdd_get_concurrency_mode();
8422
8423#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8424 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8425 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8426 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8427 return TRUE;
8428#endif
8429
Jeff Johnson295189b2012-06-20 16:38:30 -07008430 /*loop through all adapters. TBD fix for Concurrency */
8431 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8432 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8433 {
8434 pAdapter = pAdapterNode->pAdapter;
8435 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8436 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8437 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008438 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008439 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008440 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008441 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8442 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008443 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008444 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008445 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8446 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008447 return FALSE;
8448 }
8449 }
8450 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8451 pAdapterNode = pNext;
8452 }
8453 return TRUE;
8454}
8455
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008456/* Decides whether to send suspend notification to Riva
8457 * if any adapter is in BMPS; then it is required */
8458v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8459{
8460 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8461 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8462
8463 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8464 {
8465 return TRUE;
8466 }
8467 return FALSE;
8468}
8469
Jeff Johnson295189b2012-06-20 16:38:30 -07008470void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8471{
8472 switch(mode)
8473 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008474 case VOS_STA_MODE:
8475 case VOS_P2P_CLIENT_MODE:
8476 case VOS_P2P_GO_MODE:
8477 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008478 pHddCtx->concurrency_mode |= (1 << mode);
8479 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008480 break;
8481 default:
8482 break;
8483
8484 }
8485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8486 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8487}
8488
8489
8490void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8491{
8492 switch(mode)
8493 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008494 case VOS_STA_MODE:
8495 case VOS_P2P_CLIENT_MODE:
8496 case VOS_P2P_GO_MODE:
8497 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008498 pHddCtx->no_of_sessions[mode]--;
8499 if (!(pHddCtx->no_of_sessions[mode]))
8500 pHddCtx->concurrency_mode &= (~(1 << mode));
8501 break;
8502 default:
8503 break;
8504 }
8505 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8506 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8507}
8508
Jeff Johnsone7245742012-09-05 17:12:55 -07008509/**---------------------------------------------------------------------------
8510 *
8511 * \brief wlan_hdd_restart_init
8512 *
8513 * This function initalizes restart timer/flag. An internal function.
8514 *
8515 * \param - pHddCtx
8516 *
8517 * \return - None
8518 *
8519 * --------------------------------------------------------------------------*/
8520
8521static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8522{
8523 /* Initialize */
8524 pHddCtx->hdd_restart_retries = 0;
8525 atomic_set(&pHddCtx->isRestartInProgress, 0);
8526 vos_timer_init(&pHddCtx->hdd_restart_timer,
8527 VOS_TIMER_TYPE_SW,
8528 wlan_hdd_restart_timer_cb,
8529 pHddCtx);
8530}
8531/**---------------------------------------------------------------------------
8532 *
8533 * \brief wlan_hdd_restart_deinit
8534 *
8535 * This function cleans up the resources used. An internal function.
8536 *
8537 * \param - pHddCtx
8538 *
8539 * \return - None
8540 *
8541 * --------------------------------------------------------------------------*/
8542
8543static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8544{
8545
8546 VOS_STATUS vos_status;
8547 /* Block any further calls */
8548 atomic_set(&pHddCtx->isRestartInProgress, 1);
8549 /* Cleanup */
8550 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8551 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008552 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008553 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8554 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008555 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008556
8557}
8558
8559/**---------------------------------------------------------------------------
8560 *
8561 * \brief wlan_hdd_framework_restart
8562 *
8563 * This function uses a cfg80211 API to start a framework initiated WLAN
8564 * driver module unload/load.
8565 *
8566 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8567 *
8568 *
8569 * \param - pHddCtx
8570 *
8571 * \return - VOS_STATUS_SUCCESS: Success
8572 * VOS_STATUS_E_EMPTY: Adapter is Empty
8573 * VOS_STATUS_E_NOMEM: No memory
8574
8575 * --------------------------------------------------------------------------*/
8576
8577static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8578{
8579 VOS_STATUS status = VOS_STATUS_SUCCESS;
8580 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008581 int len = (sizeof (struct ieee80211_mgmt));
8582 struct ieee80211_mgmt *mgmt = NULL;
8583
8584 /* Prepare the DEAUTH managment frame with reason code */
8585 mgmt = kzalloc(len, GFP_KERNEL);
8586 if(mgmt == NULL)
8587 {
8588 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8589 "%s: memory allocation failed (%d bytes)", __func__, len);
8590 return VOS_STATUS_E_NOMEM;
8591 }
8592 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008593
8594 /* Iterate over all adapters/devices */
8595 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8596 do
8597 {
8598 if( (status == VOS_STATUS_SUCCESS) &&
8599 pAdapterNode &&
8600 pAdapterNode->pAdapter)
8601 {
8602 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8603 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8604 pAdapterNode->pAdapter->dev->name,
8605 pAdapterNode->pAdapter->device_mode,
8606 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008607 /*
8608 * CFG80211 event to restart the driver
8609 *
8610 * 'cfg80211_send_unprot_deauth' sends a
8611 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8612 * of SME(Linux Kernel) state machine.
8613 *
8614 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8615 * the driver.
8616 *
8617 */
8618
8619 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008620 }
8621 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8622 pAdapterNode = pNext;
8623 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8624
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008625
8626 /* Free the allocated management frame */
8627 kfree(mgmt);
8628
Jeff Johnsone7245742012-09-05 17:12:55 -07008629 /* Retry until we unload or reach max count */
8630 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8631 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8632
8633 return status;
8634
8635}
8636/**---------------------------------------------------------------------------
8637 *
8638 * \brief wlan_hdd_restart_timer_cb
8639 *
8640 * Restart timer callback. An internal function.
8641 *
8642 * \param - User data:
8643 *
8644 * \return - None
8645 *
8646 * --------------------------------------------------------------------------*/
8647
8648void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8649{
8650 hdd_context_t *pHddCtx = usrDataForCallback;
8651 wlan_hdd_framework_restart(pHddCtx);
8652 return;
8653
8654}
8655
8656
8657/**---------------------------------------------------------------------------
8658 *
8659 * \brief wlan_hdd_restart_driver
8660 *
8661 * This function sends an event to supplicant to restart the WLAN driver.
8662 *
8663 * This function is called from vos_wlanRestart.
8664 *
8665 * \param - pHddCtx
8666 *
8667 * \return - VOS_STATUS_SUCCESS: Success
8668 * VOS_STATUS_E_EMPTY: Adapter is Empty
8669 * VOS_STATUS_E_ALREADY: Request already in progress
8670
8671 * --------------------------------------------------------------------------*/
8672VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8673{
8674 VOS_STATUS status = VOS_STATUS_SUCCESS;
8675
8676 /* A tight check to make sure reentrancy */
8677 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8678 {
8679 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8680 "%s: WLAN restart is already in progress", __func__);
8681
8682 return VOS_STATUS_E_ALREADY;
8683 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008684 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008685#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008686 wcnss_reset_intr();
8687#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008688
Jeff Johnsone7245742012-09-05 17:12:55 -07008689 return status;
8690}
8691
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008692/*
8693 * API to find if there is any STA or P2P-Client is connected
8694 */
8695VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8696{
8697 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8698}
Jeff Johnsone7245742012-09-05 17:12:55 -07008699
Jeff Johnson295189b2012-06-20 16:38:30 -07008700//Register the module init/exit functions
8701module_init(hdd_module_init);
8702module_exit(hdd_module_exit);
8703
8704MODULE_LICENSE("Dual BSD/GPL");
8705MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8706MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8707
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008708module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8709 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008710
Jeff Johnson76052702013-04-16 13:55:05 -07008711module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07008712 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);