blob: a49e156cbdd6e3a4ef05964df034c676cd997304 [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*/
1240 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%ld\n",
1241 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,
1437 "scancount=%ld\n", pAdapter->numScanList);
1438 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 Girigowdabbd16eb2013-03-21 12:34:46 -07002689#endif
2690#ifdef FEATURE_WLAN_LFR
2691 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2692 {
2693 tANI_U8 *value = command;
2694 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2695
2696 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2697 value = value + 12;
2698 /* Convert the value from ascii to integer */
2699 ret = kstrtou8(value, 10, &lfrMode);
2700 if (ret < 0)
2701 {
2702 /* If the input value is greater than max value of datatype, then also
2703 kstrtou8 fails */
2704 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2705 "%s: kstrtou8 failed range [%d - %d]", __func__,
2706 CFG_LFR_FEATURE_ENABLED_MIN,
2707 CFG_LFR_FEATURE_ENABLED_MAX);
2708 ret = -EINVAL;
2709 goto exit;
2710 }
2711
2712 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2713 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2714 {
2715 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2716 "lfr mode value %d is out of range"
2717 " (Min: %d Max: %d)", lfrMode,
2718 CFG_LFR_FEATURE_ENABLED_MIN,
2719 CFG_LFR_FEATURE_ENABLED_MAX);
2720 ret = -EINVAL;
2721 goto exit;
2722 }
2723
2724 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2725 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2726
2727 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2728 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2729 }
2730#endif
2731#ifdef WLAN_FEATURE_VOWIFI_11R
2732 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2733 {
2734 tANI_U8 *value = command;
2735 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2736
2737 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2738 value = value + 18;
2739 /* Convert the value from ascii to integer */
2740 ret = kstrtou8(value, 10, &ft);
2741 if (ret < 0)
2742 {
2743 /* If the input value is greater than max value of datatype, then also
2744 kstrtou8 fails */
2745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2746 "%s: kstrtou8 failed range [%d - %d]", __func__,
2747 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2748 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2749 ret = -EINVAL;
2750 goto exit;
2751 }
2752
2753 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2754 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2755 {
2756 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2757 "ft mode value %d is out of range"
2758 " (Min: %d Max: %d)", ft,
2759 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2760 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2761 ret = -EINVAL;
2762 goto exit;
2763 }
2764
2765 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2766 "%s: Received Command to change ft mode = %d", __func__, ft);
2767
2768 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2769 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2770 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302771
2772 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2773 {
2774 tANI_U8 *value = command;
2775 tSirMacAddr targetApBssid;
2776 tANI_U8 trigger = 0;
2777 eHalStatus status = eHAL_STATUS_SUCCESS;
2778 hdd_station_ctx_t *pHddStaCtx = NULL;
2779 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2780
2781 /* if not associated, no need to proceed with reassoc */
2782 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2783 {
2784 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2785 ret = -EINVAL;
2786 goto exit;
2787 }
2788
2789 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2790 if (eHAL_STATUS_SUCCESS != status)
2791 {
2792 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2793 "%s: Failed to parse reassoc command data", __func__);
2794 ret = -EINVAL;
2795 goto exit;
2796 }
2797
2798 /* if the target bssid is same as currently associated AP,
2799 then no need to proceed with reassoc */
2800 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2801 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2802 {
2803 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2804 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2805 __func__);
2806 ret = -EINVAL;
2807 goto exit;
2808 }
2809
2810 /* Proceed with scan/roam */
2811 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2812 &targetApBssid[0],
2813 (tSmeFastRoamTrigger)(trigger));
2814 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002815#endif
2816#ifdef FEATURE_WLAN_CCX
2817 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2818 {
2819 tANI_U8 *value = command;
2820 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2821
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002822 /* Check if the features OKC/CCX/11R are supported simultaneously,
2823 then this operation is not permitted (return FAILURE) */
2824 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2825 hdd_is_okc_mode_enabled(pHddCtx) &&
2826 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2827 {
2828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2829 "%s: OKC/CCX/11R are supported simultaneously"
2830 " hence this operation is not permitted!", __func__);
2831 ret = -EPERM;
2832 goto exit;
2833 }
2834
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002835 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2836 value = value + 11;
2837 /* Convert the value from ascii to integer */
2838 ret = kstrtou8(value, 10, &ccxMode);
2839 if (ret < 0)
2840 {
2841 /* If the input value is greater than max value of datatype, then also
2842 kstrtou8 fails */
2843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2844 "%s: kstrtou8 failed range [%d - %d]", __func__,
2845 CFG_CCX_FEATURE_ENABLED_MIN,
2846 CFG_CCX_FEATURE_ENABLED_MAX);
2847 ret = -EINVAL;
2848 goto exit;
2849 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002850 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2851 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2852 {
2853 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2854 "Ccx mode value %d is out of range"
2855 " (Min: %d Max: %d)", ccxMode,
2856 CFG_CCX_FEATURE_ENABLED_MIN,
2857 CFG_CCX_FEATURE_ENABLED_MAX);
2858 ret = -EINVAL;
2859 goto exit;
2860 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2862 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
2863
2864 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
2865 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
2866 }
2867#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002868 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
2869 {
2870 tANI_U8 *value = command;
2871 tANI_BOOLEAN roamScanControl = 0;
2872
2873 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
2874 value = value + 19;
2875 /* Convert the value from ascii to integer */
2876 ret = kstrtou8(value, 10, &roamScanControl);
2877 if (ret < 0)
2878 {
2879 /* If the input value is greater than max value of datatype, then also
2880 kstrtou8 fails */
2881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2882 "%s: kstrtou8 failed ", __func__);
2883 ret = -EINVAL;
2884 goto exit;
2885 }
2886
2887 if (0 != roamScanControl)
2888 {
2889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2890 "roam scan control invalid value = %d",
2891 roamScanControl);
2892 ret = -EINVAL;
2893 goto exit;
2894 }
2895 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2896 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
2897
2898 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
2899 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002900#ifdef FEATURE_WLAN_OKC
2901 else if (strncmp(command, "SETOKCMODE", 10) == 0)
2902 {
2903 tANI_U8 *value = command;
2904 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
2905
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002906 /* Check if the features OKC/CCX/11R are supported simultaneously,
2907 then this operation is not permitted (return FAILURE) */
2908 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2909 hdd_is_okc_mode_enabled(pHddCtx) &&
2910 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2911 {
2912 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2913 "%s: OKC/CCX/11R are supported simultaneously"
2914 " hence this operation is not permitted!", __func__);
2915 ret = -EPERM;
2916 goto exit;
2917 }
2918
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002919 /* Move pointer to ahead of SETOKCMODE<delimiter> */
2920 value = value + 11;
2921 /* Convert the value from ascii to integer */
2922 ret = kstrtou8(value, 10, &okcMode);
2923 if (ret < 0)
2924 {
2925 /* If the input value is greater than max value of datatype, then also
2926 kstrtou8 fails */
2927 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2928 "%s: kstrtou8 failed range [%d - %d]", __func__,
2929 CFG_OKC_FEATURE_ENABLED_MIN,
2930 CFG_OKC_FEATURE_ENABLED_MAX);
2931 ret = -EINVAL;
2932 goto exit;
2933 }
2934
2935 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
2936 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
2937 {
2938 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2939 "Okc mode value %d is out of range"
2940 " (Min: %d Max: %d)", okcMode,
2941 CFG_OKC_FEATURE_ENABLED_MIN,
2942 CFG_OKC_FEATURE_ENABLED_MAX);
2943 ret = -EINVAL;
2944 goto exit;
2945 }
2946
2947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2948 "%s: Received Command to change okc mode = %d", __func__, okcMode);
2949
2950 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
2951 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002952 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
2953 {
2954 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
2955 char extra[32];
2956 tANI_U8 len = 0;
2957
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002958 len = scnprintf(extra, sizeof(extra), "%s %d",
2959 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002960 if (copy_to_user(priv_data.buf, &extra, len + 1))
2961 {
2962 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2963 "%s: failed to copy data to user buffer", __func__);
2964 ret = -EFAULT;
2965 goto exit;
2966 }
2967 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002968#endif
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05302969#ifdef WLAN_FEATURE_PACKET_FILTERING
2970 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
2971 {
2972 tANI_U8 filterType = 0;
2973 tANI_U8 *value = command;
2974
2975 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
2976 value = value + 22;
2977
2978 /* Convert the value from ascii to integer */
2979 ret = kstrtou8(value, 10, &filterType);
2980 if (ret < 0)
2981 {
2982 /* If the input value is greater than max value of datatype,
2983 * then also kstrtou8 fails
2984 */
2985 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2986 "%s: kstrtou8 failed range ", __func__);
2987 ret = -EINVAL;
2988 goto exit;
2989 }
2990
2991 if (filterType != 0 && filterType != 1)
2992 {
2993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2994 "%s: Accepted Values are 0 and 1 ", __func__);
2995 ret = -EINVAL;
2996 goto exit;
2997 }
2998 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
2999 pAdapter->sessionId);
3000 }
3001#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303002 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3003 {
3004 char *dhcpPhase;
3005 dhcpPhase = command + 12;
3006 if ('1' == *dhcpPhase)
3007 {
3008 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3009 pAdapter->macAddressCurrent.bytes);
3010 }
3011 else if ('2' == *dhcpPhase)
3012 {
3013 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3014 pAdapter->macAddressCurrent.bytes);
3015 }
3016 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003017 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3018 {
3019 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3020 }
3021 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3022 {
3023 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3024 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303025 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3026 {
3027 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3028 char extra[32];
3029 tANI_U8 len = 0;
3030
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003031 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303032 (int)pCfg->nActiveMaxChnTime);
3033 if (copy_to_user(priv_data.buf, &extra, len + 1))
3034 {
3035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3036 "%s: failed to copy data to user buffer", __func__);
3037 ret = -EFAULT;
3038 goto exit;
3039 }
3040 ret = len;
3041 }
3042 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3043 {
3044 tANI_U8 *value = command;
3045 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3046 int val = 0, temp;
3047
3048 value = value + 13;
3049 temp = kstrtou32(value, 10, &val);
3050 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3051 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3052 {
3053 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3054 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3055 ret = -EFAULT;
3056 goto exit;
3057 }
3058 pCfg->nActiveMaxChnTime = val;
3059 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003060 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3061 {
3062 tANI_U8 filterType = 0;
3063 tANI_U8 *value;
3064 value = command + 9;
3065
3066 /* Convert the value from ascii to integer */
3067 ret = kstrtou8(value, 10, &filterType);
3068 if (ret < 0)
3069 {
3070 /* If the input value is greater than max value of datatype,
3071 * then also kstrtou8 fails
3072 */
3073 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3074 "%s: kstrtou8 failed range ", __func__);
3075 ret = -EINVAL;
3076 goto exit;
3077 }
3078 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3079 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3080 {
3081 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3082 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3083 " 2-Sink ", __func__);
3084 ret = -EINVAL;
3085 goto exit;
3086 }
3087 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3088 pHddCtx->drvr_miracast = filterType;
3089 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3090 }
Leo Chang614d2072013-08-22 14:59:44 -07003091 else if (strncmp(command, "SETMCRATE", 9) == 0)
3092 {
3093 int rc;
3094 tANI_U8 *value = command;
3095 int targetRate;
3096
3097 /* Only valid for SAP mode */
3098 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3099 {
3100 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3101 "%s: SAP mode is not running", __func__);
3102 ret = -EFAULT;
3103 goto exit;
3104 }
3105
3106 /* Move pointer to ahead of SETMCRATE<delimiter> */
3107 /* input value is in units of hundred kbps */
3108 value = value + 10;
3109 /* Convert the value from ascii to integer, decimal base */
3110 ret = kstrtouint(value, 10, &targetRate);
3111
3112 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
3113 if (rc)
3114 {
3115 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3116 "%s: Set MC Rate Fail %d", __func__, rc);
3117 ret = -EFAULT;
3118 goto exit;
3119 }
3120 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303121#ifdef FEATURE_WLAN_BATCH_SCAN
3122 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3123 {
3124 char extra[32];
3125 tANI_U8 len = 0;
3126 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3127
3128 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3129 {
3130 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3131 "%s: Batch scan feature is not supported by FW", __func__);
3132 ret = -EINVAL;
3133 goto exit;
3134 }
3135
3136 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3137 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3138 {
3139 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3140 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3141 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3142 " mode",
3143 pAdapter->device_mode);
3144 ret = -EINVAL;
3145 goto exit;
3146 }
3147
3148 len = snprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
3149 version);
3150 if (copy_to_user(priv_data.buf, &extra, len + 1))
3151 {
3152 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3153 "%s: failed to copy data to user buffer", __func__);
3154 ret = -EFAULT;
3155 goto exit;
3156 }
3157 ret = HDD_BATCH_SCAN_VERSION;
3158 }
3159 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3160 {
3161 int status;
3162 tANI_U8 *value = (command + 16);
3163 eHalStatus halStatus;
3164 unsigned long rc;
3165 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3166 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3167
3168 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3169 {
3170 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3171 "%s: Batch scan feature is not supported by FW", __func__);
3172 ret = -EINVAL;
3173 goto exit;
3174 }
3175
Rajeev Kumar20140c12013-10-21 19:39:02 -07003176
Rajeev79dbe4c2013-10-05 11:03:42 +05303177 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3178 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3179 {
3180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003181 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303182 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3183 pAdapter->device_mode);
3184 ret = -EINVAL;
3185 goto exit;
3186 }
3187
Rajeev Kumar20140c12013-10-21 19:39:02 -07003188
Rajeev79dbe4c2013-10-05 11:03:42 +05303189 status = hdd_parse_set_batchscan_command(value, pReq);
3190 if (status)
3191 {
3192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003193 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303194 ret = -EINVAL;
3195 goto exit;
3196 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003197
3198
Rajeev79dbe4c2013-10-05 11:03:42 +05303199 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3200 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3201 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3202 pAdapter);
3203
3204 if ( eHAL_STATUS_SUCCESS == halStatus )
3205 {
3206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3207 "sme_SetBatchScanReq returned success halStatus %d",
3208 halStatus);
3209 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3210 {
3211 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3212 rc = wait_for_completion_timeout(
3213 &pAdapter->hdd_set_batch_scan_req_var,
3214 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3215 if (0 == rc)
3216 {
3217 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3218 "%s: Timeout waiting for set batch scan to complete",
3219 __func__);
3220 ret = -EINVAL;
3221 goto exit;
3222 }
3223 }
3224 if ( !pRsp->nScansToBatch )
3225 {
3226 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3227 "%s: Received set batch scan failure response from FW",
3228 __func__, pRsp->nScansToBatch);
3229 ret = -EINVAL;
3230 goto exit;
3231 }
3232 /*As per the Batch Scan Framework API we should return the MIN of
3233 either MSCAN or the max # of scans firmware can cache*/
3234 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3235
Rajeev Kumar20140c12013-10-21 19:39:02 -07003236 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3237
Rajeev79dbe4c2013-10-05 11:03:42 +05303238 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3239 "%s: request MSCAN %d response MSCAN %d ret %d",
3240 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3241 }
3242 else
3243 {
3244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3245 "sme_SetBatchScanReq returned failure halStatus %d",
3246 halStatus);
3247 ret = -EINVAL;
3248 goto exit;
3249 }
3250 }
3251 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3252 {
3253 eHalStatus halStatus;
3254 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3255 pInd->param = 0;
3256
3257 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3258 {
3259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3260 "%s: Batch scan feature is not supported by FW", __func__);
3261 ret = -EINVAL;
3262 goto exit;
3263 }
3264
Rajeev Kumar20140c12013-10-21 19:39:02 -07003265 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303266 {
3267 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003268 "Batch scan is not yet enabled batch scan state %d",
3269 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303270 ret = -EINVAL;
3271 goto exit;
3272 }
3273
Rajeev Kumar20140c12013-10-21 19:39:02 -07003274 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3275
Rajeev79dbe4c2013-10-05 11:03:42 +05303276 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3277 pAdapter->sessionId);
3278 if ( eHAL_STATUS_SUCCESS == halStatus )
3279 {
3280 ret = 0;
3281 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3282 "sme_StopBatchScanInd returned success halStatus %d",
3283 halStatus);
3284 }
3285 else
3286 {
3287 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3288 "sme_StopBatchScanInd returned failure halStatus %d",
3289 halStatus);
3290 ret = -EINVAL;
3291 goto exit;
3292 }
3293 }
3294 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3295 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003296 tANI_U32 remain_len;
3297
Rajeev79dbe4c2013-10-05 11:03:42 +05303298 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3299 {
3300 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3301 "%s: Batch scan feature is not supported by FW", __func__);
3302 ret = -EINVAL;
3303 goto exit;
3304 }
3305
Rajeev Kumar20140c12013-10-21 19:39:02 -07003306 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303307 {
3308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003309 "Batch scan is not yet enabled could not return results"
3310 "Batch Scan state %d",
3311 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303312 ret = -EINVAL;
3313 goto exit;
3314 }
3315
3316 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003317 remain_len = priv_data.total_len - priv_data.used_len;
3318 if (remain_len < priv_data.total_len)
3319 {
3320 /*Clear previous batch scan response data if any*/
3321 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3322 }
3323 else
3324 {
3325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3326 "Invalid total length from user space can't fetch batch"
3327 " scan response total_len %ld used_len %ld remain len %ld",
3328 priv_data.total_len, priv_data.used_len, remain_len);
3329 ret = -EINVAL;
3330 goto exit;
3331 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303332 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3333 }
3334#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003335#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3336 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3337 {
3338 tANI_U8 *value = command;
3339 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3340 tANI_U8 numChannels = 0;
3341 eHalStatus status = eHAL_STATUS_SUCCESS;
3342
3343 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3344 if (eHAL_STATUS_SUCCESS != status)
3345 {
3346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3347 "%s: Failed to parse channel list information", __func__);
3348 ret = -EINVAL;
3349 goto exit;
3350 }
3351
3352 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3353 {
3354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3355 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3356 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3357 ret = -EINVAL;
3358 goto exit;
3359 }
3360 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3361 ChannelList,
3362 numChannels);
3363 if (eHAL_STATUS_SUCCESS != status)
3364 {
3365 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3366 "%s: Failed to update channel list information", __func__);
3367 ret = -EINVAL;
3368 goto exit;
3369 }
3370 }
3371 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3372 {
3373 tANI_U8 *value = command;
3374 char extra[128] = {0};
3375 int len = 0;
3376 tANI_U8 tid = 0;
3377 hdd_station_ctx_t *pHddStaCtx = NULL;
3378 tAniTrafStrmMetrics tsmMetrics;
3379 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3380
3381 /* if not associated, return error */
3382 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3383 {
3384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3385 ret = -EINVAL;
3386 goto exit;
3387 }
3388
3389 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3390 value = value + 12;
3391 /* Convert the value from ascii to integer */
3392 ret = kstrtou8(value, 10, &tid);
3393 if (ret < 0)
3394 {
3395 /* If the input value is greater than max value of datatype, then also
3396 kstrtou8 fails */
3397 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3398 "%s: kstrtou8 failed range [%d - %d]", __func__,
3399 TID_MIN_VALUE,
3400 TID_MAX_VALUE);
3401 ret = -EINVAL;
3402 goto exit;
3403 }
3404
3405 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3406 {
3407 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3408 "tid value %d is out of range"
3409 " (Min: %d Max: %d)", tid,
3410 TID_MIN_VALUE,
3411 TID_MAX_VALUE);
3412 ret = -EINVAL;
3413 goto exit;
3414 }
3415
3416 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3417 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3418
3419 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3420 {
3421 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3422 "%s: failed to get tsm stats", __func__);
3423 ret = -EFAULT;
3424 goto exit;
3425 }
3426
3427 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3428 "UplinkPktQueueDly(%d)\n"
3429 "UplinkPktQueueDlyHist[0](%d)\n"
3430 "UplinkPktQueueDlyHist[1](%d)\n"
3431 "UplinkPktQueueDlyHist[2](%d)\n"
3432 "UplinkPktQueueDlyHist[3](%d)\n"
3433 "UplinkPktTxDly(%lu)\n"
3434 "UplinkPktLoss(%d)\n"
3435 "UplinkPktCount(%d)\n"
3436 "RoamingCount(%d)\n"
3437 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3438 tsmMetrics.UplinkPktQueueDlyHist[0],
3439 tsmMetrics.UplinkPktQueueDlyHist[1],
3440 tsmMetrics.UplinkPktQueueDlyHist[2],
3441 tsmMetrics.UplinkPktQueueDlyHist[3],
3442 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3443 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3444
3445 /* Output TSM stats is of the format
3446 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3447 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
3448 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %lu %d %d %d %d", command,
3449 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3450 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3451 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3452 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3453 tsmMetrics.RoamingDly);
3454
3455 if (copy_to_user(priv_data.buf, &extra, len + 1))
3456 {
3457 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3458 "%s: failed to copy data to user buffer", __func__);
3459 ret = -EFAULT;
3460 goto exit;
3461 }
3462 }
3463 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3464 {
3465 tANI_U8 *value = command;
3466 tANI_U8 *cckmIe = NULL;
3467 tANI_U8 cckmIeLen = 0;
3468 eHalStatus status = eHAL_STATUS_SUCCESS;
3469
3470 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3471 if (eHAL_STATUS_SUCCESS != status)
3472 {
3473 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3474 "%s: Failed to parse cckm ie data", __func__);
3475 ret = -EINVAL;
3476 goto exit;
3477 }
3478
3479 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3480 {
3481 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3482 "%s: CCKM Ie input length is more than max[%d]", __func__,
3483 DOT11F_IE_RSN_MAX_LEN);
3484 if (NULL != cckmIe)
3485 {
3486 vos_mem_free(cckmIe);
3487 }
3488 ret = -EINVAL;
3489 goto exit;
3490 }
3491 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3492 if (NULL != cckmIe)
3493 {
3494 vos_mem_free(cckmIe);
3495 }
3496 }
3497#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003498 else {
3499 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3500 __func__, command);
3501 }
3502
Jeff Johnson295189b2012-06-20 16:38:30 -07003503 }
3504exit:
3505 if (command)
3506 {
3507 kfree(command);
3508 }
3509 return ret;
3510}
3511
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003512
3513
3514#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3515static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3516{
3517 struct statsContext *pStatsContext = NULL;
3518 hdd_adapter_t *pAdapter = NULL;
3519
3520 if (NULL == pContext)
3521 {
3522 hddLog(VOS_TRACE_LEVEL_ERROR,
3523 "%s: Bad param, pContext [%p]",
3524 __func__, pContext);
3525 return;
3526 }
3527
3528 /* there is a race condition that exists between this callback function
3529 and the caller since the caller could time out either before or
3530 while this code is executing. we'll assume the timeout hasn't
3531 occurred, but we'll verify that right before we save our work */
3532
3533 pStatsContext = pContext;
3534 pAdapter = pStatsContext->pAdapter;
3535 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3536 {
3537 /* the caller presumably timed out so there is nothing we can do */
3538 hddLog(VOS_TRACE_LEVEL_WARN,
3539 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3540 __func__, pAdapter, pStatsContext->magic);
3541 return;
3542 }
3543
3544 /* the race is on. caller could have timed out immediately after
3545 we verified the magic, but if so, caller will wait a short time
3546 for us to copy over the tsm stats */
3547 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3548 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3549 tsmMetrics.UplinkPktQueueDlyHist,
3550 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3551 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3552 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3553 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3554 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3555 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3556 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3557
3558 /* and notify the caller */
3559 complete(&pStatsContext->completion);
3560}
3561
3562
3563
3564static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3565 tAniTrafStrmMetrics* pTsmMetrics)
3566{
3567 hdd_station_ctx_t *pHddStaCtx = NULL;
3568 eHalStatus hstatus;
3569 long lrc;
3570 struct statsContext context;
3571 hdd_context_t *pHddCtx = NULL;
3572
3573 if (NULL == pAdapter)
3574 {
3575 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3576 return VOS_STATUS_E_FAULT;
3577 }
3578
3579 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3580 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3581
3582 /* we are connected prepare our callback context */
3583 init_completion(&context.completion);
3584 context.pAdapter = pAdapter;
3585 context.magic = STATS_CONTEXT_MAGIC;
3586
3587 /* query tsm stats */
3588 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3589 pHddStaCtx->conn_info.staId[ 0 ],
3590 pHddStaCtx->conn_info.bssId,
3591 &context, pHddCtx->pvosContext, tid);
3592
3593 if (eHAL_STATUS_SUCCESS != hstatus)
3594 {
3595 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3596 return hstatus;
3597 }
3598 else
3599 {
3600 /* request was sent -- wait for the response */
3601 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3602 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3603 /* either we have a response or we timed out
3604 either way, first invalidate our magic */
3605 context.magic = 0;
3606 if (lrc <= 0)
3607 {
3608 hddLog(VOS_TRACE_LEVEL_ERROR,
3609 "%s: SME %s while retrieving statistics",
3610 __func__, (0 == lrc) ? "timeout" : "interrupt");
3611 /* there is a race condition such that the callback
3612 function could be executing at the same time we are. of
3613 primary concern is if the callback function had already
3614 verified the "magic" but hasn't yet set the completion
3615 variable. Since the completion variable is on our
3616 stack, we'll delay just a bit to make sure the data is
3617 still valid if that is the case */
3618 msleep(50);
3619 return (VOS_STATUS_E_TIMEOUT);
3620 }
3621 }
3622 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3623 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3624 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3625 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3626 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3627 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3628 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3629 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3630 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3631 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3632
3633 return VOS_STATUS_SUCCESS;
3634}
3635#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3636
Srinivas Girigowdade697412013-02-14 16:31:48 -08003637#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3638void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3639{
3640 eCsrBand band = -1;
3641 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3642 switch (band)
3643 {
3644 case eCSR_BAND_ALL:
3645 *pBand = WLAN_HDD_UI_BAND_AUTO;
3646 break;
3647
3648 case eCSR_BAND_24:
3649 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3650 break;
3651
3652 case eCSR_BAND_5G:
3653 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3654 break;
3655
3656 default:
3657 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3658 *pBand = -1;
3659 break;
3660 }
3661}
3662
3663/**---------------------------------------------------------------------------
3664
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003665 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3666
3667 This function parses the send action frame data passed in the format
3668 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3669
Srinivas Girigowda56076852013-08-20 14:00:50 -07003670 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003671 \param - pTargetApBssid Pointer to target Ap bssid
3672 \param - pChannel Pointer to the Target AP channel
3673 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3674 \param - pBuf Pointer to data
3675 \param - pBufLen Pointer to data length
3676
3677 \return - 0 for success non-zero for failure
3678
3679 --------------------------------------------------------------------------*/
3680VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3681 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3682{
3683 tANI_U8 *inPtr = pValue;
3684 tANI_U8 *dataEnd;
3685 int tempInt;
3686 int j = 0;
3687 int i = 0;
3688 int v = 0;
3689 tANI_U8 tempBuf[32];
3690 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003691 /* 12 hexa decimal digits and 5 ':' */
3692 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003693
3694 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3695 /*no argument after the command*/
3696 if (NULL == inPtr)
3697 {
3698 return -EINVAL;
3699 }
3700
3701 /*no space after the command*/
3702 else if (SPACE_ASCII_VALUE != *inPtr)
3703 {
3704 return -EINVAL;
3705 }
3706
3707 /*removing empty spaces*/
3708 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3709
3710 /*no argument followed by spaces*/
3711 if ('\0' == *inPtr)
3712 {
3713 return -EINVAL;
3714 }
3715
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003716 v = sscanf(inPtr, "%17s", macAddress);
3717 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003718 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3720 "Invalid MAC address or All hex inputs are not read (%d)", v);
3721 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003722 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003723
3724 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3725 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3726 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3727 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3728 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3729 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003730
3731 /* point to the next argument */
3732 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3733 /*no argument after the command*/
3734 if (NULL == inPtr) return -EINVAL;
3735
3736 /*removing empty spaces*/
3737 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3738
3739 /*no argument followed by spaces*/
3740 if ('\0' == *inPtr)
3741 {
3742 return -EINVAL;
3743 }
3744
3745 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003746 v = sscanf(inPtr, "%32s ", tempBuf);
3747 if (1 != v) return -EINVAL;
3748
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003749 v = kstrtos32(tempBuf, 10, &tempInt);
3750 if ( v < 0) return -EINVAL;
3751
3752 *pChannel = tempInt;
3753
3754 /* point to the next argument */
3755 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3756 /*no argument after the command*/
3757 if (NULL == inPtr) return -EINVAL;
3758 /*removing empty spaces*/
3759 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3760
3761 /*no argument followed by spaces*/
3762 if ('\0' == *inPtr)
3763 {
3764 return -EINVAL;
3765 }
3766
3767 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003768 v = sscanf(inPtr, "%32s ", tempBuf);
3769 if (1 != v) return -EINVAL;
3770
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003771 v = kstrtos32(tempBuf, 10, &tempInt);
3772 if ( v < 0) return -EINVAL;
3773
3774 *pDwellTime = tempInt;
3775
3776 /* point to the next argument */
3777 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3778 /*no argument after the command*/
3779 if (NULL == inPtr) return -EINVAL;
3780 /*removing empty spaces*/
3781 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3782
3783 /*no argument followed by spaces*/
3784 if ('\0' == *inPtr)
3785 {
3786 return -EINVAL;
3787 }
3788
3789 /* find the length of data */
3790 dataEnd = inPtr;
3791 while(('\0' != *dataEnd) )
3792 {
3793 dataEnd++;
3794 ++(*pBufLen);
3795 }
3796 if ( *pBufLen <= 0) return -EINVAL;
3797
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07003798 /* Allocate the number of bytes based on the number of input characters
3799 whether it is even or odd.
3800 if the number of input characters are even, then we need N/2 byte.
3801 if the number of input characters are odd, then we need do (N+1)/2 to
3802 compensate rounding off.
3803 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
3804 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
3805 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003806 if (NULL == *pBuf)
3807 {
3808 hddLog(VOS_TRACE_LEVEL_FATAL,
3809 "%s: vos_mem_alloc failed ", __func__);
3810 return -EINVAL;
3811 }
3812
3813 /* the buffer received from the upper layer is character buffer,
3814 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
3815 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
3816 and f0 in 3rd location */
3817 for (i = 0, j = 0; j < *pBufLen; j += 2)
3818 {
3819 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
3820 (*pBuf)[i++] = tempByte;
3821 }
3822 *pBufLen = i;
3823 return VOS_STATUS_SUCCESS;
3824}
3825
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003826/**---------------------------------------------------------------------------
3827
Srinivas Girigowdade697412013-02-14 16:31:48 -08003828 \brief hdd_parse_channellist() - HDD Parse channel list
3829
3830 This function parses the channel list passed in the format
3831 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003832 if the Number of channels (N) does not match with the actual number of channels passed
3833 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
3834 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
3835 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
3836 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08003837
3838 \param - pValue Pointer to input channel list
3839 \param - ChannelList Pointer to local output array to record channel list
3840 \param - pNumChannels Pointer to number of roam scan channels
3841
3842 \return - 0 for success non-zero for failure
3843
3844 --------------------------------------------------------------------------*/
3845VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
3846{
3847 tANI_U8 *inPtr = pValue;
3848 int tempInt;
3849 int j = 0;
3850 int v = 0;
3851 char buf[32];
3852
3853 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3854 /*no argument after the command*/
3855 if (NULL == inPtr)
3856 {
3857 return -EINVAL;
3858 }
3859
3860 /*no space after the command*/
3861 else if (SPACE_ASCII_VALUE != *inPtr)
3862 {
3863 return -EINVAL;
3864 }
3865
3866 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003867 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003868
3869 /*no argument followed by spaces*/
3870 if ('\0' == *inPtr)
3871 {
3872 return -EINVAL;
3873 }
3874
3875 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003876 v = sscanf(inPtr, "%32s ", buf);
3877 if (1 != v) return -EINVAL;
3878
Srinivas Girigowdade697412013-02-14 16:31:48 -08003879 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003880 if ((v < 0) ||
3881 (tempInt <= 0) ||
3882 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
3883 {
3884 return -EINVAL;
3885 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003886
3887 *pNumChannels = tempInt;
3888
3889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3890 "Number of channels are: %d", *pNumChannels);
3891
3892 for (j = 0; j < (*pNumChannels); j++)
3893 {
3894 /*inPtr pointing to the beginning of first space after number of channels*/
3895 inPtr = strpbrk( inPtr, " " );
3896 /*no channel list after the number of channels argument*/
3897 if (NULL == inPtr)
3898 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003899 if (0 != j)
3900 {
3901 *pNumChannels = j;
3902 return VOS_STATUS_SUCCESS;
3903 }
3904 else
3905 {
3906 return -EINVAL;
3907 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003908 }
3909
3910 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003911 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003912
3913 /*no channel list after the number of channels argument and spaces*/
3914 if ( '\0' == *inPtr )
3915 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003916 if (0 != j)
3917 {
3918 *pNumChannels = j;
3919 return VOS_STATUS_SUCCESS;
3920 }
3921 else
3922 {
3923 return -EINVAL;
3924 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003925 }
3926
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003927 v = sscanf(inPtr, "%32s ", buf);
3928 if (1 != v) return -EINVAL;
3929
Srinivas Girigowdade697412013-02-14 16:31:48 -08003930 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003931 if ((v < 0) ||
3932 (tempInt <= 0) ||
3933 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3934 {
3935 return -EINVAL;
3936 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003937 pChannelList[j] = tempInt;
3938
3939 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3940 "Channel %d added to preferred channel list",
3941 pChannelList[j] );
3942 }
3943
Srinivas Girigowdade697412013-02-14 16:31:48 -08003944 return VOS_STATUS_SUCCESS;
3945}
3946
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003947
3948/**---------------------------------------------------------------------------
3949
3950 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
3951
3952 This function parses the reasoc command data passed in the format
3953 REASSOC<space><bssid><space><channel>
3954
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003955 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003956 \param - pTargetApBssid Pointer to target Ap bssid
3957 \param - pChannel Pointer to the Target AP channel
3958
3959 \return - 0 for success non-zero for failure
3960
3961 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003962VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
3963 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003964{
3965 tANI_U8 *inPtr = pValue;
3966 int tempInt;
3967 int v = 0;
3968 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003969 /* 12 hexa decimal digits and 5 ':' */
3970 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003971
3972 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3973 /*no argument after the command*/
3974 if (NULL == inPtr)
3975 {
3976 return -EINVAL;
3977 }
3978
3979 /*no space after the command*/
3980 else if (SPACE_ASCII_VALUE != *inPtr)
3981 {
3982 return -EINVAL;
3983 }
3984
3985 /*removing empty spaces*/
3986 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3987
3988 /*no argument followed by spaces*/
3989 if ('\0' == *inPtr)
3990 {
3991 return -EINVAL;
3992 }
3993
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003994 v = sscanf(inPtr, "%17s", macAddress);
3995 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003996 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3998 "Invalid MAC address or All hex inputs are not read (%d)", v);
3999 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004000 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004001
4002 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4003 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4004 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4005 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4006 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4007 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004008
4009 /* point to the next argument */
4010 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4011 /*no argument after the command*/
4012 if (NULL == inPtr) return -EINVAL;
4013
4014 /*removing empty spaces*/
4015 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4016
4017 /*no argument followed by spaces*/
4018 if ('\0' == *inPtr)
4019 {
4020 return -EINVAL;
4021 }
4022
4023 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004024 v = sscanf(inPtr, "%32s ", tempBuf);
4025 if (1 != v) return -EINVAL;
4026
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004027 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004028 if ((v < 0) ||
4029 (tempInt <= 0) ||
4030 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4031 {
4032 return -EINVAL;
4033 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004034
4035 *pChannel = tempInt;
4036 return VOS_STATUS_SUCCESS;
4037}
4038
4039#endif
4040
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004041#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4042/**---------------------------------------------------------------------------
4043
4044 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4045
4046 This function parses the SETCCKM IE command
4047 SETCCKMIE<space><ie data>
4048
4049 \param - pValue Pointer to input data
4050 \param - pCckmIe Pointer to output cckm Ie
4051 \param - pCckmIeLen Pointer to output cckm ie length
4052
4053 \return - 0 for success non-zero for failure
4054
4055 --------------------------------------------------------------------------*/
4056VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4057 tANI_U8 *pCckmIeLen)
4058{
4059 tANI_U8 *inPtr = pValue;
4060 tANI_U8 *dataEnd;
4061 int j = 0;
4062 int i = 0;
4063 tANI_U8 tempByte = 0;
4064
4065 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4066 /*no argument after the command*/
4067 if (NULL == inPtr)
4068 {
4069 return -EINVAL;
4070 }
4071
4072 /*no space after the command*/
4073 else if (SPACE_ASCII_VALUE != *inPtr)
4074 {
4075 return -EINVAL;
4076 }
4077
4078 /*removing empty spaces*/
4079 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4080
4081 /*no argument followed by spaces*/
4082 if ('\0' == *inPtr)
4083 {
4084 return -EINVAL;
4085 }
4086
4087 /* find the length of data */
4088 dataEnd = inPtr;
4089 while(('\0' != *dataEnd) )
4090 {
4091 dataEnd++;
4092 ++(*pCckmIeLen);
4093 }
4094 if ( *pCckmIeLen <= 0) return -EINVAL;
4095
4096 /* Allocate the number of bytes based on the number of input characters
4097 whether it is even or odd.
4098 if the number of input characters are even, then we need N/2 byte.
4099 if the number of input characters are odd, then we need do (N+1)/2 to
4100 compensate rounding off.
4101 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4102 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4103 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4104 if (NULL == *pCckmIe)
4105 {
4106 hddLog(VOS_TRACE_LEVEL_FATAL,
4107 "%s: vos_mem_alloc failed ", __func__);
4108 return -EINVAL;
4109 }
4110 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4111 /* the buffer received from the upper layer is character buffer,
4112 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4113 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4114 and f0 in 3rd location */
4115 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4116 {
4117 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4118 (*pCckmIe)[i++] = tempByte;
4119 }
4120 *pCckmIeLen = i;
4121
4122 return VOS_STATUS_SUCCESS;
4123}
4124#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4125
Jeff Johnson295189b2012-06-20 16:38:30 -07004126/**---------------------------------------------------------------------------
4127
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004128 \brief hdd_is_valid_mac_address() - Validate MAC address
4129
4130 This function validates whether the given MAC address is valid or not
4131 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4132 where X is the hexa decimal digit character and separated by ':'
4133 This algorithm works even if MAC address is not separated by ':'
4134
4135 This code checks given input string mac contains exactly 12 hexadecimal digits.
4136 and a separator colon : appears in the input string only after
4137 an even number of hex digits.
4138
4139 \param - pMacAddr pointer to the input MAC address
4140 \return - 1 for valid and 0 for invalid
4141
4142 --------------------------------------------------------------------------*/
4143
4144v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4145{
4146 int xdigit = 0;
4147 int separator = 0;
4148 while (*pMacAddr)
4149 {
4150 if (isxdigit(*pMacAddr))
4151 {
4152 xdigit++;
4153 }
4154 else if (':' == *pMacAddr)
4155 {
4156 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4157 break;
4158
4159 ++separator;
4160 }
4161 else
4162 {
4163 separator = -1;
4164 /* Invalid MAC found */
4165 return 0;
4166 }
4167 ++pMacAddr;
4168 }
4169 return (xdigit == 12 && (separator == 5 || separator == 0));
4170}
4171
4172/**---------------------------------------------------------------------------
4173
Jeff Johnson295189b2012-06-20 16:38:30 -07004174 \brief hdd_open() - HDD Open function
4175
4176 This is called in response to ifconfig up
4177
4178 \param - dev Pointer to net_device structure
4179
4180 \return - 0 for success non-zero for failure
4181
4182 --------------------------------------------------------------------------*/
4183int hdd_open (struct net_device *dev)
4184{
4185 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4186 hdd_context_t *pHddCtx;
4187 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4188 VOS_STATUS status;
4189 v_BOOL_t in_standby = TRUE;
4190
4191 if (NULL == pAdapter)
4192 {
4193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004194 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004195 return -ENODEV;
4196 }
4197
4198 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4199 if (NULL == pHddCtx)
4200 {
4201 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004202 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004203 return -ENODEV;
4204 }
4205
4206 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4207 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4208 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004209 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4210 {
4211 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304212 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004213 in_standby = FALSE;
4214 break;
4215 }
4216 else
4217 {
4218 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4219 pAdapterNode = pNext;
4220 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004221 }
4222
4223 if (TRUE == in_standby)
4224 {
4225 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4226 {
4227 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4228 "wlan out of power save", __func__);
4229 return -EINVAL;
4230 }
4231 }
4232
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004233 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004234 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4235 {
4236 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004237 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004238 /* Enable TX queues only when we are connected */
4239 netif_tx_start_all_queues(dev);
4240 }
4241
4242 return 0;
4243}
4244
4245int hdd_mon_open (struct net_device *dev)
4246{
4247 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4248
4249 if(pAdapter == NULL) {
4250 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004251 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004252 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004253 }
4254
4255 netif_start_queue(dev);
4256
4257 return 0;
4258}
4259/**---------------------------------------------------------------------------
4260
4261 \brief hdd_stop() - HDD stop function
4262
4263 This is called in response to ifconfig down
4264
4265 \param - dev Pointer to net_device structure
4266
4267 \return - 0 for success non-zero for failure
4268
4269 --------------------------------------------------------------------------*/
4270
4271int hdd_stop (struct net_device *dev)
4272{
4273 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4274 hdd_context_t *pHddCtx;
4275 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4276 VOS_STATUS status;
4277 v_BOOL_t enter_standby = TRUE;
4278
4279 ENTER();
4280
4281 if (NULL == pAdapter)
4282 {
4283 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004284 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004285 return -ENODEV;
4286 }
4287
4288 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4289 if (NULL == pHddCtx)
4290 {
4291 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004292 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004293 return -ENODEV;
4294 }
4295
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004296 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004297 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4298 netif_tx_disable(pAdapter->dev);
4299 netif_carrier_off(pAdapter->dev);
4300
4301
4302 /* SoftAP ifaces should never go in power save mode
4303 making sure same here. */
4304 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4305 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004306 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004307 )
4308 {
4309 /* SoftAP mode, so return from here */
4310 EXIT();
4311 return 0;
4312 }
4313
4314 /* Find if any iface is up then
4315 if any iface is up then can't put device to sleep/ power save mode. */
4316 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4317 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4318 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004319 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4320 {
4321 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304322 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004323 enter_standby = FALSE;
4324 break;
4325 }
4326 else
4327 {
4328 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4329 pAdapterNode = pNext;
4330 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004331 }
4332
4333 if (TRUE == enter_standby)
4334 {
4335 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4336 "entering standby", __func__);
4337 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4338 {
4339 /*log and return success*/
4340 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4341 "wlan in power save", __func__);
4342 }
4343 }
4344
4345 EXIT();
4346 return 0;
4347}
4348
4349/**---------------------------------------------------------------------------
4350
4351 \brief hdd_uninit() - HDD uninit function
4352
4353 This is called during the netdev unregister to uninitialize all data
4354associated with the device
4355
4356 \param - dev Pointer to net_device structure
4357
4358 \return - void
4359
4360 --------------------------------------------------------------------------*/
4361static void hdd_uninit (struct net_device *dev)
4362{
4363 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4364
4365 ENTER();
4366
4367 do
4368 {
4369 if (NULL == pAdapter)
4370 {
4371 hddLog(VOS_TRACE_LEVEL_FATAL,
4372 "%s: NULL pAdapter", __func__);
4373 break;
4374 }
4375
4376 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4377 {
4378 hddLog(VOS_TRACE_LEVEL_FATAL,
4379 "%s: Invalid magic", __func__);
4380 break;
4381 }
4382
4383 if (NULL == pAdapter->pHddCtx)
4384 {
4385 hddLog(VOS_TRACE_LEVEL_FATAL,
4386 "%s: NULL pHddCtx", __func__);
4387 break;
4388 }
4389
4390 if (dev != pAdapter->dev)
4391 {
4392 hddLog(VOS_TRACE_LEVEL_FATAL,
4393 "%s: Invalid device reference", __func__);
4394 /* we haven't validated all cases so let this go for now */
4395 }
4396
4397 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4398
4399 /* after uninit our adapter structure will no longer be valid */
4400 pAdapter->dev = NULL;
4401 pAdapter->magic = 0;
4402 } while (0);
4403
4404 EXIT();
4405}
4406
4407/**---------------------------------------------------------------------------
4408
4409 \brief hdd_release_firmware() -
4410
4411 This function calls the release firmware API to free the firmware buffer.
4412
4413 \param - pFileName Pointer to the File Name.
4414 pCtx - Pointer to the adapter .
4415
4416
4417 \return - 0 for success, non zero for failure
4418
4419 --------------------------------------------------------------------------*/
4420
4421VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4422{
4423 VOS_STATUS status = VOS_STATUS_SUCCESS;
4424 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4425 ENTER();
4426
4427
4428 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4429
4430 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4431
4432 if(pHddCtx->fw) {
4433 release_firmware(pHddCtx->fw);
4434 pHddCtx->fw = NULL;
4435 }
4436 else
4437 status = VOS_STATUS_E_FAILURE;
4438 }
4439 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4440 if(pHddCtx->nv) {
4441 release_firmware(pHddCtx->nv);
4442 pHddCtx->nv = NULL;
4443 }
4444 else
4445 status = VOS_STATUS_E_FAILURE;
4446
4447 }
4448
4449 EXIT();
4450 return status;
4451}
4452
4453/**---------------------------------------------------------------------------
4454
4455 \brief hdd_request_firmware() -
4456
4457 This function reads the firmware file using the request firmware
4458 API and returns the the firmware data and the firmware file size.
4459
4460 \param - pfileName - Pointer to the file name.
4461 - pCtx - Pointer to the adapter .
4462 - ppfw_data - Pointer to the pointer of the firmware data.
4463 - pSize - Pointer to the file size.
4464
4465 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4466
4467 --------------------------------------------------------------------------*/
4468
4469
4470VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4471{
4472 int status;
4473 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4474 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4475 ENTER();
4476
4477 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4478
4479 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4480
4481 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4482 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4483 __func__, pfileName);
4484 retval = VOS_STATUS_E_FAILURE;
4485 }
4486
4487 else {
4488 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4489 *pSize = pHddCtx->fw->size;
4490 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4491 __func__, *pSize);
4492 }
4493 }
4494 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4495
4496 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4497
4498 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4499 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4500 __func__, pfileName);
4501 retval = VOS_STATUS_E_FAILURE;
4502 }
4503
4504 else {
4505 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4506 *pSize = pHddCtx->nv->size;
4507 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4508 __func__, *pSize);
4509 }
4510 }
4511
4512 EXIT();
4513 return retval;
4514}
4515/**---------------------------------------------------------------------------
4516 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4517
4518 This is the function invoked by SME to inform the result of a full power
4519 request issued by HDD
4520
4521 \param - callbackcontext - Pointer to cookie
4522 status - result of request
4523
4524 \return - None
4525
4526--------------------------------------------------------------------------*/
4527void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4528{
4529 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4530
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004531 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004532 if(&pHddCtx->full_pwr_comp_var)
4533 {
4534 complete(&pHddCtx->full_pwr_comp_var);
4535 }
4536}
4537
4538/**---------------------------------------------------------------------------
4539
4540 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4541
4542 This is the function invoked by SME to inform the result of BMPS
4543 request issued by HDD
4544
4545 \param - callbackcontext - Pointer to cookie
4546 status - result of request
4547
4548 \return - None
4549
4550--------------------------------------------------------------------------*/
4551void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4552{
4553
4554 struct completion *completion_var = (struct completion*) callbackContext;
4555
4556 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4557 if(completion_var != NULL)
4558 {
4559 complete(completion_var);
4560 }
4561}
4562
4563/**---------------------------------------------------------------------------
4564
4565 \brief hdd_get_cfg_file_size() -
4566
4567 This function reads the configuration file using the request firmware
4568 API and returns the configuration file size.
4569
4570 \param - pCtx - Pointer to the adapter .
4571 - pFileName - Pointer to the file name.
4572 - pBufSize - Pointer to the buffer size.
4573
4574 \return - 0 for success, non zero for failure
4575
4576 --------------------------------------------------------------------------*/
4577
4578VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4579{
4580 int status;
4581 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4582
4583 ENTER();
4584
4585 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4586
4587 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4588 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4589 status = VOS_STATUS_E_FAILURE;
4590 }
4591 else {
4592 *pBufSize = pHddCtx->fw->size;
4593 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4594 release_firmware(pHddCtx->fw);
4595 pHddCtx->fw = NULL;
4596 }
4597
4598 EXIT();
4599 return VOS_STATUS_SUCCESS;
4600}
4601
4602/**---------------------------------------------------------------------------
4603
4604 \brief hdd_read_cfg_file() -
4605
4606 This function reads the configuration file using the request firmware
4607 API and returns the cfg data and the buffer size of the configuration file.
4608
4609 \param - pCtx - Pointer to the adapter .
4610 - pFileName - Pointer to the file name.
4611 - pBuffer - Pointer to the data buffer.
4612 - pBufSize - Pointer to the buffer size.
4613
4614 \return - 0 for success, non zero for failure
4615
4616 --------------------------------------------------------------------------*/
4617
4618VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4619 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4620{
4621 int status;
4622 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4623
4624 ENTER();
4625
4626 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4627
4628 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4629 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4630 return VOS_STATUS_E_FAILURE;
4631 }
4632 else {
4633 if(*pBufSize != pHddCtx->fw->size) {
4634 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4635 "file size", __func__);
4636 release_firmware(pHddCtx->fw);
4637 pHddCtx->fw = NULL;
4638 return VOS_STATUS_E_FAILURE;
4639 }
4640 else {
4641 if(pBuffer) {
4642 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4643 }
4644 release_firmware(pHddCtx->fw);
4645 pHddCtx->fw = NULL;
4646 }
4647 }
4648
4649 EXIT();
4650
4651 return VOS_STATUS_SUCCESS;
4652}
4653
4654/**---------------------------------------------------------------------------
4655
Jeff Johnson295189b2012-06-20 16:38:30 -07004656 \brief hdd_set_mac_address() -
4657
4658 This function sets the user specified mac address using
4659 the command ifconfig wlanX hw ether <mac adress>.
4660
4661 \param - dev - Pointer to the net device.
4662 - addr - Pointer to the sockaddr.
4663 \return - 0 for success, non zero for failure
4664
4665 --------------------------------------------------------------------------*/
4666
4667static int hdd_set_mac_address(struct net_device *dev, void *addr)
4668{
4669 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4670 struct sockaddr *psta_mac_addr = addr;
4671 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4672
4673 ENTER();
4674
4675 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4676
4677#ifdef HDD_SESSIONIZE
4678 // set the MAC address though the STA ID CFG.
4679 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4680 (v_U8_t *)&pAdapter->macAddressCurrent,
4681 sizeof( pAdapter->macAddressCurrent ),
4682 hdd_set_mac_addr_cb, VOS_FALSE );
4683#endif
4684
4685 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4686
4687 EXIT();
4688 return halStatus;
4689}
4690
4691tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4692{
4693 int i;
4694 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4695 {
4696 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4697 break;
4698 }
4699
4700 if( VOS_MAX_CONCURRENCY_PERSONA == i)
4701 return NULL;
4702
4703 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
4704 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
4705}
4706
4707void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
4708{
4709 int i;
4710 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4711 {
4712 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
4713 {
4714 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
4715 break;
4716 }
4717 }
4718 return;
4719}
4720
4721#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4722 static struct net_device_ops wlan_drv_ops = {
4723 .ndo_open = hdd_open,
4724 .ndo_stop = hdd_stop,
4725 .ndo_uninit = hdd_uninit,
4726 .ndo_start_xmit = hdd_hard_start_xmit,
4727 .ndo_tx_timeout = hdd_tx_timeout,
4728 .ndo_get_stats = hdd_stats,
4729 .ndo_do_ioctl = hdd_ioctl,
4730 .ndo_set_mac_address = hdd_set_mac_address,
4731 .ndo_select_queue = hdd_select_queue,
4732#ifdef WLAN_FEATURE_PACKET_FILTERING
4733#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
4734 .ndo_set_rx_mode = hdd_set_multicast_list,
4735#else
4736 .ndo_set_multicast_list = hdd_set_multicast_list,
4737#endif //LINUX_VERSION_CODE
4738#endif
4739 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004740 static struct net_device_ops wlan_mon_drv_ops = {
4741 .ndo_open = hdd_mon_open,
4742 .ndo_stop = hdd_stop,
4743 .ndo_uninit = hdd_uninit,
4744 .ndo_start_xmit = hdd_mon_hard_start_xmit,
4745 .ndo_tx_timeout = hdd_tx_timeout,
4746 .ndo_get_stats = hdd_stats,
4747 .ndo_do_ioctl = hdd_ioctl,
4748 .ndo_set_mac_address = hdd_set_mac_address,
4749 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004750
4751#endif
4752
4753void hdd_set_station_ops( struct net_device *pWlanDev )
4754{
4755#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4756 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
4757 pWlanDev->netdev_ops = &wlan_drv_ops;
4758#else
4759 pWlanDev->open = hdd_open;
4760 pWlanDev->stop = hdd_stop;
4761 pWlanDev->uninit = hdd_uninit;
4762 pWlanDev->hard_start_xmit = NULL;
4763 pWlanDev->tx_timeout = hdd_tx_timeout;
4764 pWlanDev->get_stats = hdd_stats;
4765 pWlanDev->do_ioctl = hdd_ioctl;
4766 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
4767 pWlanDev->set_mac_address = hdd_set_mac_address;
4768#endif
4769}
4770
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004771static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07004772{
4773 struct net_device *pWlanDev = NULL;
4774 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004775 /*
4776 * cfg80211 initialization and registration....
4777 */
4778 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
4779
Jeff Johnson295189b2012-06-20 16:38:30 -07004780 if(pWlanDev != NULL)
4781 {
4782
4783 //Save the pointer to the net_device in the HDD adapter
4784 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
4785
Jeff Johnson295189b2012-06-20 16:38:30 -07004786 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
4787
4788 pAdapter->dev = pWlanDev;
4789 pAdapter->pHddCtx = pHddCtx;
4790 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
4791
4792 init_completion(&pAdapter->session_open_comp_var);
4793 init_completion(&pAdapter->session_close_comp_var);
4794 init_completion(&pAdapter->disconnect_comp_var);
4795 init_completion(&pAdapter->linkup_event_var);
4796 init_completion(&pAdapter->cancel_rem_on_chan_var);
4797 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004798#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4799 init_completion(&pAdapter->offchannel_tx_event);
4800#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004801 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004802#ifdef FEATURE_WLAN_TDLS
4803 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07004804 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08004805 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05304806 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004807#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004808 init_completion(&pHddCtx->mc_sus_event_var);
4809 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05304810 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07004811 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07004812 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07004813
Rajeev79dbe4c2013-10-05 11:03:42 +05304814#ifdef FEATURE_WLAN_BATCH_SCAN
4815 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
4816 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
4817 pAdapter->pBatchScanRsp = NULL;
4818 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07004819 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05304820 mutex_init(&pAdapter->hdd_batch_scan_lock);
4821#endif
4822
Jeff Johnson295189b2012-06-20 16:38:30 -07004823 pAdapter->isLinkUpSvcNeeded = FALSE;
4824 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
4825 //Init the net_device structure
4826 strlcpy(pWlanDev->name, name, IFNAMSIZ);
4827
4828 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
4829 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
4830 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
4831 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
4832
4833 hdd_set_station_ops( pAdapter->dev );
4834
4835 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004836 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
4837 pAdapter->wdev.wiphy = pHddCtx->wiphy;
4838 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004839 /* set pWlanDev's parent to underlying device */
4840 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
4841 }
4842
4843 return pAdapter;
4844}
4845
4846VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
4847{
4848 struct net_device *pWlanDev = pAdapter->dev;
4849 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4850 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4851 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4852
4853 if( rtnl_lock_held )
4854 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08004855 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
4857 {
4858 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
4859 return VOS_STATUS_E_FAILURE;
4860 }
4861 }
4862 if (register_netdevice(pWlanDev))
4863 {
4864 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
4865 return VOS_STATUS_E_FAILURE;
4866 }
4867 }
4868 else
4869 {
4870 if(register_netdev(pWlanDev))
4871 {
4872 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
4873 return VOS_STATUS_E_FAILURE;
4874 }
4875 }
4876 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
4877
4878 return VOS_STATUS_SUCCESS;
4879}
4880
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004881static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07004882{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004883 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07004884
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004885 if (NULL == pAdapter)
4886 {
4887 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
4888 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07004889 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004890
4891 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4892 {
4893 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
4894 return eHAL_STATUS_NOT_INITIALIZED;
4895 }
4896
4897 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
4898
4899 /* need to make sure all of our scheduled work has completed.
4900 * This callback is called from MC thread context, so it is safe to
4901 * to call below flush workqueue API from here.
4902 */
4903 flush_scheduled_work();
4904
4905 /* We can be blocked while waiting for scheduled work to be
4906 * flushed, and the adapter structure can potentially be freed, in
4907 * which case the magic will have been reset. So make sure the
4908 * magic is still good, and hence the adapter structure is still
4909 * valid, before signaling completion */
4910 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
4911 {
4912 complete(&pAdapter->session_close_comp_var);
4913 }
4914
Jeff Johnson295189b2012-06-20 16:38:30 -07004915 return eHAL_STATUS_SUCCESS;
4916}
4917
4918VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
4919{
4920 struct net_device *pWlanDev = pAdapter->dev;
4921 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4922 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4923 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4924 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4925 int rc = 0;
4926
4927 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004928 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07004929 //Open a SME session for future operation
4930 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004931 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004932 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4933 {
4934 hddLog(VOS_TRACE_LEVEL_FATAL,
4935 "sme_OpenSession() failed with status code %08d [x%08lx]",
4936 halStatus, halStatus );
4937 status = VOS_STATUS_E_FAILURE;
4938 goto error_sme_open;
4939 }
4940
4941 //Block on a completion variable. Can't wait forever though.
4942 rc = wait_for_completion_interruptible_timeout(
4943 &pAdapter->session_open_comp_var,
4944 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
4945 if (!rc)
4946 {
4947 hddLog(VOS_TRACE_LEVEL_FATAL,
4948 "Session is not opened within timeout period code %08d", rc );
4949 status = VOS_STATUS_E_FAILURE;
4950 goto error_sme_open;
4951 }
4952
4953 // Register wireless extensions
4954 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
4955 {
4956 hddLog(VOS_TRACE_LEVEL_FATAL,
4957 "hdd_register_wext() failed with status code %08d [x%08lx]",
4958 halStatus, halStatus );
4959 status = VOS_STATUS_E_FAILURE;
4960 goto error_register_wext;
4961 }
4962 //Safe to register the hard_start_xmit function again
4963#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4964 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
4965#else
4966 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
4967#endif
4968
4969 //Set the Connection State to Not Connected
4970 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
4971
4972 //Set the default operation channel
4973 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
4974
4975 /* Make the default Auth Type as OPEN*/
4976 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
4977
4978 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
4979 {
4980 hddLog(VOS_TRACE_LEVEL_FATAL,
4981 "hdd_init_tx_rx() failed with status code %08d [x%08lx]",
4982 status, status );
4983 goto error_init_txrx;
4984 }
4985
4986 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
4987
4988 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
4989 {
4990 hddLog(VOS_TRACE_LEVEL_FATAL,
4991 "hdd_wmm_adapter_init() failed with status code %08d [x%08lx]",
4992 status, status );
4993 goto error_wmm_init;
4994 }
4995
4996 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
4997
Gopichand Nakkala4327a152013-03-04 23:22:42 -08004998#ifdef FEATURE_WLAN_TDLS
4999 if(0 != wlan_hdd_tdls_init(pAdapter))
5000 {
5001 status = VOS_STATUS_E_FAILURE;
5002 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5003 goto error_tdls_init;
5004 }
5005 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5006#endif
5007
Jeff Johnson295189b2012-06-20 16:38:30 -07005008 return VOS_STATUS_SUCCESS;
5009
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005010#ifdef FEATURE_WLAN_TDLS
5011error_tdls_init:
5012 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5013 hdd_wmm_adapter_close(pAdapter);
5014#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005015error_wmm_init:
5016 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5017 hdd_deinit_tx_rx(pAdapter);
5018error_init_txrx:
5019 hdd_UnregisterWext(pWlanDev);
5020error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005021 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005022 {
5023 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005024 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005025 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005026 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005027 {
5028 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005029 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005030 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005031 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005032 }
5033}
5034error_sme_open:
5035 return status;
5036}
5037
Jeff Johnson295189b2012-06-20 16:38:30 -07005038void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5039{
5040 hdd_cfg80211_state_t *cfgState;
5041
5042 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5043
5044 if( NULL != cfgState->buf )
5045 {
5046 int rc;
5047 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5048 rc = wait_for_completion_interruptible_timeout(
5049 &pAdapter->tx_action_cnf_event,
5050 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5051 if(!rc)
5052 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005053 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005054 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5055 }
5056 }
5057 return;
5058}
Jeff Johnson295189b2012-06-20 16:38:30 -07005059
5060void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5061{
5062 ENTER();
5063 switch ( pAdapter->device_mode )
5064 {
5065 case WLAN_HDD_INFRA_STATION:
5066 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005067 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005068 {
5069 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5070 {
5071 hdd_deinit_tx_rx( pAdapter );
5072 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5073 }
5074
5075 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5076 {
5077 hdd_wmm_adapter_close( pAdapter );
5078 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5079 }
5080
Jeff Johnson295189b2012-06-20 16:38:30 -07005081 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005082#ifdef FEATURE_WLAN_TDLS
5083 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5084 {
5085 wlan_hdd_tdls_exit(pAdapter);
5086 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5087 }
5088#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005089
5090 break;
5091 }
5092
5093 case WLAN_HDD_SOFTAP:
5094 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005095 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305096
5097 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5098 {
5099 hdd_wmm_adapter_close( pAdapter );
5100 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5101 }
5102
Jeff Johnson295189b2012-06-20 16:38:30 -07005103 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005104
5105 hdd_unregister_hostapd(pAdapter);
5106 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005107 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005108 break;
5109 }
5110
5111 case WLAN_HDD_MONITOR:
5112 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005113 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005114 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5115 {
5116 hdd_deinit_tx_rx( pAdapter );
5117 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5118 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005119 if(NULL != pAdapterforTx)
5120 {
5121 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5122 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005123 break;
5124 }
5125
5126
5127 default:
5128 break;
5129 }
5130
5131 EXIT();
5132}
5133
5134void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5135{
5136 struct net_device *pWlanDev = pAdapter->dev;
5137
Rajeev79dbe4c2013-10-05 11:03:42 +05305138#ifdef FEATURE_WLAN_BATCH_SCAN
5139 tHddBatchScanRsp *pNode;
5140 tHddBatchScanRsp *pPrev;
5141 if (pAdapter)
5142 {
5143 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5144 pNode = pAdapter->pBatchScanRsp;
5145 while (pNode)
5146 {
5147 pPrev = pNode;
5148 pNode = pNode->pNext;
5149 vos_mem_free((v_VOID_t * )pPrev);
5150 }
5151 pAdapter->pBatchScanRsp = NULL;
5152 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5153 }
5154#endif
5155
Jeff Johnson295189b2012-06-20 16:38:30 -07005156 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5157 if( rtnl_held )
5158 {
5159 unregister_netdevice(pWlanDev);
5160 }
5161 else
5162 {
5163 unregister_netdev(pWlanDev);
5164 }
5165 // note that the pAdapter is no longer valid at this point
5166 // since the memory has been reclaimed
5167 }
5168
5169}
5170
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005171void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5172{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305173 VOS_STATUS status;
5174 hdd_adapter_t *pAdapter = NULL;
5175 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005176
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305177 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005178
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305179 /*loop through all adapters.*/
5180 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005181 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305182 pAdapter = pAdapterNode->pAdapter;
5183 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5184 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005185
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305186 { // we skip this registration for modes other than STA and P2P client modes.
5187 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5188 pAdapterNode = pNext;
5189 continue;
5190 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005191
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305192 //Apply Dynamic DTIM For P2P
5193 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5194 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5195 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5196 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5197 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5198 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5199 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5200 (eConnectionState_Associated ==
5201 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5202 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5203 {
5204 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005205
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305206 powerRequest.uIgnoreDTIM = 1;
5207 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5208
5209 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5210 {
5211 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5212 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5213 }
5214 else
5215 {
5216 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5217 }
5218
5219 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5220 * specified during Enter/Exit BMPS when LCD off*/
5221 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5222 NULL, eANI_BOOLEAN_FALSE);
5223 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5224 NULL, eANI_BOOLEAN_FALSE);
5225
5226 /* switch to the DTIM specified in cfg.ini */
5227 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5228 "Switch to DTIM %d", powerRequest.uListenInterval);
5229 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5230 break;
5231
5232 }
5233
5234 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5235 pAdapterNode = pNext;
5236 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005237}
5238
5239void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5240{
5241 /*Switch back to DTIM 1*/
5242 tSirSetPowerParamsReq powerRequest = { 0 };
5243
5244 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5245 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005246 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005247
5248 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5249 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5250 NULL, eANI_BOOLEAN_FALSE);
5251 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5252 NULL, eANI_BOOLEAN_FALSE);
5253
5254 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5255 "Switch to DTIM%d",powerRequest.uListenInterval);
5256 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5257
5258}
5259
Jeff Johnson295189b2012-06-20 16:38:30 -07005260VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5261{
5262 VOS_STATUS status = VOS_STATUS_SUCCESS;
5263
5264 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5265 {
5266 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5267 }
5268
5269 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5270 {
5271 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5272 }
5273
5274 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5275 {
5276 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5277 }
5278
5279 return status;
5280}
5281
5282VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5283{
5284 hdd_adapter_t *pAdapter = NULL;
5285 eHalStatus halStatus;
5286 VOS_STATUS status = VOS_STATUS_E_INVAL;
5287 v_BOOL_t disableBmps = FALSE;
5288 v_BOOL_t disableImps = FALSE;
5289
5290 switch(session_type)
5291 {
5292 case WLAN_HDD_INFRA_STATION:
5293 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005294 case WLAN_HDD_P2P_CLIENT:
5295 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005296 //Exit BMPS -> Is Sta/P2P Client is already connected
5297 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5298 if((NULL != pAdapter)&&
5299 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5300 {
5301 disableBmps = TRUE;
5302 }
5303
5304 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5305 if((NULL != pAdapter)&&
5306 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5307 {
5308 disableBmps = TRUE;
5309 }
5310
5311 //Exit both Bmps and Imps incase of Go/SAP Mode
5312 if((WLAN_HDD_SOFTAP == session_type) ||
5313 (WLAN_HDD_P2P_GO == session_type))
5314 {
5315 disableBmps = TRUE;
5316 disableImps = TRUE;
5317 }
5318
5319 if(TRUE == disableImps)
5320 {
5321 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5322 {
5323 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5324 }
5325 }
5326
5327 if(TRUE == disableBmps)
5328 {
5329 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5330 {
5331 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5332
5333 if(eHAL_STATUS_SUCCESS != halStatus)
5334 {
5335 status = VOS_STATUS_E_FAILURE;
5336 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5337 VOS_ASSERT(0);
5338 return status;
5339 }
5340 }
5341
5342 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5343 {
5344 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5345
5346 if(eHAL_STATUS_SUCCESS != halStatus)
5347 {
5348 status = VOS_STATUS_E_FAILURE;
5349 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5350 VOS_ASSERT(0);
5351 return status;
5352 }
5353 }
5354 }
5355
5356 if((TRUE == disableBmps) ||
5357 (TRUE == disableImps))
5358 {
5359 /* Now, get the chip into Full Power now */
5360 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5361 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5362 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5363
5364 if(halStatus != eHAL_STATUS_SUCCESS)
5365 {
5366 if(halStatus == eHAL_STATUS_PMC_PENDING)
5367 {
5368 //Block on a completion variable. Can't wait forever though
5369 wait_for_completion_interruptible_timeout(
5370 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5371 }
5372 else
5373 {
5374 status = VOS_STATUS_E_FAILURE;
5375 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5376 VOS_ASSERT(0);
5377 return status;
5378 }
5379 }
5380
5381 status = VOS_STATUS_SUCCESS;
5382 }
5383
5384 break;
5385 }
5386 return status;
5387}
5388
5389hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005390 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005391 tANI_U8 rtnl_held )
5392{
5393 hdd_adapter_t *pAdapter = NULL;
5394 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5395 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5396 VOS_STATUS exitbmpsStatus;
5397
5398 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5399
5400 //Disable BMPS incase of Concurrency
5401 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5402
5403 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5404 {
5405 //Fail to Exit BMPS
5406 VOS_ASSERT(0);
5407 return NULL;
5408 }
5409
5410 switch(session_type)
5411 {
5412 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005414 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005415 {
5416 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5417
5418 if( NULL == pAdapter )
5419 return NULL;
5420
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305421#ifdef FEATURE_WLAN_TDLS
5422 /* A Mutex Lock is introduced while changing/initializing the mode to
5423 * protect the concurrent access for the Adapters by TDLS module.
5424 */
5425 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5426 {
5427 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5428 "%s: unable to lock list", __func__);
5429 return NULL;
5430 }
5431#endif
5432
Jeff Johnsone7245742012-09-05 17:12:55 -07005433 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5434 NL80211_IFTYPE_P2P_CLIENT:
5435 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005436
Jeff Johnson295189b2012-06-20 16:38:30 -07005437 pAdapter->device_mode = session_type;
5438
5439 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305440#ifdef FEATURE_WLAN_TDLS
5441 mutex_unlock(&pHddCtx->tdls_lock);
5442#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005443 if( VOS_STATUS_SUCCESS != status )
5444 goto err_free_netdev;
5445
5446 status = hdd_register_interface( pAdapter, rtnl_held );
5447 if( VOS_STATUS_SUCCESS != status )
5448 {
5449 hdd_deinit_adapter(pHddCtx, pAdapter);
5450 goto err_free_netdev;
5451 }
5452 //Stop the Interface TX queue.
5453 netif_tx_disable(pAdapter->dev);
5454 //netif_tx_disable(pWlanDev);
5455 netif_carrier_off(pAdapter->dev);
5456
5457 break;
5458 }
5459
Jeff Johnson295189b2012-06-20 16:38:30 -07005460 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005461 case WLAN_HDD_SOFTAP:
5462 {
5463 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5464 if( NULL == pAdapter )
5465 return NULL;
5466
Jeff Johnson295189b2012-06-20 16:38:30 -07005467 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5468 NL80211_IFTYPE_AP:
5469 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005470 pAdapter->device_mode = session_type;
5471
5472 status = hdd_init_ap_mode(pAdapter);
5473 if( VOS_STATUS_SUCCESS != status )
5474 goto err_free_netdev;
5475
5476 status = hdd_register_hostapd( pAdapter, rtnl_held );
5477 if( VOS_STATUS_SUCCESS != status )
5478 {
5479 hdd_deinit_adapter(pHddCtx, pAdapter);
5480 goto err_free_netdev;
5481 }
5482
5483 netif_tx_disable(pAdapter->dev);
5484 netif_carrier_off(pAdapter->dev);
5485
5486 hdd_set_conparam( 1 );
5487 break;
5488 }
5489 case WLAN_HDD_MONITOR:
5490 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005491 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5492 if( NULL == pAdapter )
5493 return NULL;
5494
5495 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5496 pAdapter->device_mode = session_type;
5497 status = hdd_register_interface( pAdapter, rtnl_held );
5498#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5499 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5500#else
5501 pAdapter->dev->open = hdd_mon_open;
5502 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5503#endif
5504 hdd_init_tx_rx( pAdapter );
5505 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5506 //Set adapter to be used for data tx. It will use either GO or softap.
5507 pAdapter->sessionCtx.monitor.pAdapterForTx =
5508 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005509 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5510 {
5511 pAdapter->sessionCtx.monitor.pAdapterForTx =
5512 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5513 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005514 /* This workqueue will be used to transmit management packet over
5515 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005516 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5517 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5518 return NULL;
5519 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005520
Jeff Johnson295189b2012-06-20 16:38:30 -07005521 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5522 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005523 }
5524 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005525 case WLAN_HDD_FTM:
5526 {
5527 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5528
5529 if( NULL == pAdapter )
5530 return NULL;
5531 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5532 * message while loading driver in FTM mode. */
5533 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5534 pAdapter->device_mode = session_type;
5535 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305536
5537 hdd_init_tx_rx( pAdapter );
5538
5539 //Stop the Interface TX queue.
5540 netif_tx_disable(pAdapter->dev);
5541 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005542 }
5543 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005544 default:
5545 {
5546 VOS_ASSERT(0);
5547 return NULL;
5548 }
5549 }
5550
5551
5552 if( VOS_STATUS_SUCCESS == status )
5553 {
5554 //Add it to the hdd's session list.
5555 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5556 if( NULL == pHddAdapterNode )
5557 {
5558 status = VOS_STATUS_E_NOMEM;
5559 }
5560 else
5561 {
5562 pHddAdapterNode->pAdapter = pAdapter;
5563 status = hdd_add_adapter_back ( pHddCtx,
5564 pHddAdapterNode );
5565 }
5566 }
5567
5568 if( VOS_STATUS_SUCCESS != status )
5569 {
5570 if( NULL != pAdapter )
5571 {
5572 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5573 pAdapter = NULL;
5574 }
5575 if( NULL != pHddAdapterNode )
5576 {
5577 vos_mem_free( pHddAdapterNode );
5578 }
5579
5580 goto resume_bmps;
5581 }
5582
5583 if(VOS_STATUS_SUCCESS == status)
5584 {
5585 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5586
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005587 //Initialize the WoWL service
5588 if(!hdd_init_wowl(pAdapter))
5589 {
5590 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5591 goto err_free_netdev;
5592 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005593 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005594 return pAdapter;
5595
5596err_free_netdev:
5597 free_netdev(pAdapter->dev);
5598 wlan_hdd_release_intf_addr( pHddCtx,
5599 pAdapter->macAddressCurrent.bytes );
5600
5601resume_bmps:
5602 //If bmps disabled enable it
5603 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5604 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305605 if (pHddCtx->hdd_wlan_suspended)
5606 {
5607 hdd_set_pwrparams(pHddCtx);
5608 }
5609 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005610 }
5611 return NULL;
5612}
5613
5614VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5615 tANI_U8 rtnl_held )
5616{
5617 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5618 VOS_STATUS status;
5619
5620 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5621 if( VOS_STATUS_SUCCESS != status )
5622 return status;
5623
5624 while ( pCurrent->pAdapter != pAdapter )
5625 {
5626 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5627 if( VOS_STATUS_SUCCESS != status )
5628 break;
5629
5630 pCurrent = pNext;
5631 }
5632 pAdapterNode = pCurrent;
5633 if( VOS_STATUS_SUCCESS == status )
5634 {
5635 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5636 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305637
5638#ifdef FEATURE_WLAN_TDLS
5639
5640 /* A Mutex Lock is introduced while changing/initializing the mode to
5641 * protect the concurrent access for the Adapters by TDLS module.
5642 */
5643 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5644 {
5645 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5646 "%s: unable to lock list", __func__);
5647 return VOS_STATUS_E_FAILURE;
5648 }
5649#endif
5650
Jeff Johnson295189b2012-06-20 16:38:30 -07005651 hdd_remove_adapter( pHddCtx, pAdapterNode );
5652 vos_mem_free( pAdapterNode );
5653
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305654#ifdef FEATURE_WLAN_TDLS
5655 mutex_unlock(&pHddCtx->tdls_lock);
5656#endif
5657
Jeff Johnson295189b2012-06-20 16:38:30 -07005658
5659 /* If there is a single session of STA/P2P client, re-enable BMPS */
5660 if ((!vos_concurrent_sessions_running()) &&
5661 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5662 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5663 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305664 if (pHddCtx->hdd_wlan_suspended)
5665 {
5666 hdd_set_pwrparams(pHddCtx);
5667 }
5668 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005669 }
5670
5671 return VOS_STATUS_SUCCESS;
5672 }
5673
5674 return VOS_STATUS_E_FAILURE;
5675}
5676
5677VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5678{
5679 hdd_adapter_list_node_t *pHddAdapterNode;
5680 VOS_STATUS status;
5681
5682 ENTER();
5683
5684 do
5685 {
5686 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5687 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5688 {
5689 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
5690 vos_mem_free( pHddAdapterNode );
5691 }
5692 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
5693
5694 EXIT();
5695
5696 return VOS_STATUS_SUCCESS;
5697}
5698
5699void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
5700{
5701 v_U8_t addIE[1] = {0};
5702
5703 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5704 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
5705 eANI_BOOLEAN_FALSE) )
5706 {
5707 hddLog(LOGE,
5708 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
5709 }
5710
5711 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5712 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
5713 eANI_BOOLEAN_FALSE) )
5714 {
5715 hddLog(LOGE,
5716 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
5717 }
5718
5719 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5720 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
5721 eANI_BOOLEAN_FALSE) )
5722 {
5723 hddLog(LOGE,
5724 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
5725 }
5726}
5727
5728VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5729{
5730 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5731 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5732 union iwreq_data wrqu;
5733
5734 ENTER();
5735
5736 switch(pAdapter->device_mode)
5737 {
5738 case WLAN_HDD_INFRA_STATION:
5739 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005740 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005741 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5742 {
5743 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
5744 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5745 pAdapter->sessionId,
5746 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5747 else
5748 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5749 pAdapter->sessionId,
5750 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5751 //success implies disconnect command got queued up successfully
5752 if(halStatus == eHAL_STATUS_SUCCESS)
5753 {
5754 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
5755 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5756 }
5757 memset(&wrqu, '\0', sizeof(wrqu));
5758 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5759 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5760 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
5761 }
5762 else
5763 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305764 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005765 }
5766
5767 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
5768 {
5769 INIT_COMPLETION(pAdapter->session_close_comp_var);
5770 if (eHAL_STATUS_SUCCESS ==
5771 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
5772 hdd_smeCloseSessionCallback, pAdapter))
5773 {
5774 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005775 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005776 &pAdapter->session_close_comp_var,
5777 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5778 }
5779 }
5780
5781 break;
5782
5783 case WLAN_HDD_SOFTAP:
5784 case WLAN_HDD_P2P_GO:
5785 //Any softap specific cleanup here...
5786 mutex_lock(&pHddCtx->sap_lock);
5787 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5788 {
5789 VOS_STATUS status;
5790 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5791
5792 //Stop Bss.
5793 status = WLANSAP_StopBss(pHddCtx->pvosContext);
5794 if (VOS_IS_STATUS_SUCCESS(status))
5795 {
5796 hdd_hostapd_state_t *pHostapdState =
5797 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5798
5799 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
5800
5801 if (!VOS_IS_STATUS_SUCCESS(status))
5802 {
5803 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005804 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 }
5806 }
5807 else
5808 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005809 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005810 }
5811 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
5812
5813 if (eHAL_STATUS_FAILURE ==
5814 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5815 0, NULL, eANI_BOOLEAN_FALSE))
5816 {
5817 hddLog(LOGE,
5818 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005819 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005820 }
5821
5822 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
5823 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5824 eANI_BOOLEAN_FALSE) )
5825 {
5826 hddLog(LOGE,
5827 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
5828 }
5829
5830 // Reset WNI_CFG_PROBE_RSP Flags
5831 wlan_hdd_reset_prob_rspies(pAdapter);
5832 kfree(pAdapter->sessionCtx.ap.beacon);
5833 pAdapter->sessionCtx.ap.beacon = NULL;
5834 }
5835 mutex_unlock(&pHddCtx->sap_lock);
5836 break;
5837 case WLAN_HDD_MONITOR:
5838 break;
5839 default:
5840 break;
5841 }
5842
5843 EXIT();
5844 return VOS_STATUS_SUCCESS;
5845}
5846
5847VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
5848{
5849 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5850 VOS_STATUS status;
5851 hdd_adapter_t *pAdapter;
5852
5853 ENTER();
5854
5855 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5856
5857 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5858 {
5859 pAdapter = pAdapterNode->pAdapter;
5860 netif_tx_disable(pAdapter->dev);
5861 netif_carrier_off(pAdapter->dev);
5862
5863 hdd_stop_adapter( pHddCtx, pAdapter );
5864
5865 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5866 pAdapterNode = pNext;
5867 }
5868
5869 EXIT();
5870
5871 return VOS_STATUS_SUCCESS;
5872}
5873
5874VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
5875{
5876 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5877 VOS_STATUS status;
5878 hdd_adapter_t *pAdapter;
5879
5880 ENTER();
5881
5882 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5883
5884 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5885 {
5886 pAdapter = pAdapterNode->pAdapter;
5887 netif_tx_disable(pAdapter->dev);
5888 netif_carrier_off(pAdapter->dev);
5889
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005890 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
5891
Jeff Johnson295189b2012-06-20 16:38:30 -07005892 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305893 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5894 {
5895 hdd_wmm_adapter_close( pAdapter );
5896 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5897 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005898
5899 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5900 pAdapterNode = pNext;
5901 }
5902
5903 EXIT();
5904
5905 return VOS_STATUS_SUCCESS;
5906}
5907
5908VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
5909{
5910 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5911 VOS_STATUS status;
5912 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305913 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07005914
5915 ENTER();
5916
5917 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5918
5919 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5920 {
5921 pAdapter = pAdapterNode->pAdapter;
5922
5923 switch(pAdapter->device_mode)
5924 {
5925 case WLAN_HDD_INFRA_STATION:
5926 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005927 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305928
5929 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
5930
Jeff Johnson295189b2012-06-20 16:38:30 -07005931 hdd_init_station_mode(pAdapter);
5932 /* Open the gates for HDD to receive Wext commands */
5933 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07005934 pHddCtx->scan_info.mScanPending = FALSE;
5935 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005936
5937 //Trigger the initial scan
5938 hdd_wlan_initial_scan(pAdapter);
5939
5940 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305941 if (eConnectionState_Associated == connState ||
5942 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07005943 {
5944 union iwreq_data wrqu;
5945 memset(&wrqu, '\0', sizeof(wrqu));
5946 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5947 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5948 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005949 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07005950
Jeff Johnson295189b2012-06-20 16:38:30 -07005951 /* indicate disconnected event to nl80211 */
5952 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
5953 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005954 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305955 else if (eConnectionState_Connecting == connState)
5956 {
5957 /*
5958 * Indicate connect failure to supplicant if we were in the
5959 * process of connecting
5960 */
5961 cfg80211_connect_result(pAdapter->dev, NULL,
5962 NULL, 0, NULL, 0,
5963 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
5964 GFP_KERNEL);
5965 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005966 break;
5967
5968 case WLAN_HDD_SOFTAP:
5969 /* softAP can handle SSR */
5970 break;
5971
5972 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07005973 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07005974 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07005975 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07005976 break;
5977
5978 case WLAN_HDD_MONITOR:
5979 /* monitor interface start */
5980 break;
5981 default:
5982 break;
5983 }
5984
5985 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5986 pAdapterNode = pNext;
5987 }
5988
5989 EXIT();
5990
5991 return VOS_STATUS_SUCCESS;
5992}
5993
5994VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
5995{
5996 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5997 hdd_adapter_t *pAdapter;
5998 VOS_STATUS status;
5999 v_U32_t roamId;
6000
6001 ENTER();
6002
6003 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6004
6005 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6006 {
6007 pAdapter = pAdapterNode->pAdapter;
6008
6009 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6010 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6011 {
6012 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6013 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6014
6015 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6016 init_completion(&pAdapter->disconnect_comp_var);
6017 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6018 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6019
6020 wait_for_completion_interruptible_timeout(
6021 &pAdapter->disconnect_comp_var,
6022 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6023
6024 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6025 pHddCtx->isAmpAllowed = VOS_FALSE;
6026 sme_RoamConnect(pHddCtx->hHal,
6027 pAdapter->sessionId, &(pWextState->roamProfile),
6028 &roamId);
6029 }
6030
6031 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6032 pAdapterNode = pNext;
6033 }
6034
6035 EXIT();
6036
6037 return VOS_STATUS_SUCCESS;
6038}
6039
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006040void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6041{
6042 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6043 VOS_STATUS status;
6044 hdd_adapter_t *pAdapter;
6045 hdd_station_ctx_t *pHddStaCtx;
6046 hdd_ap_ctx_t *pHddApCtx;
6047 hdd_hostapd_state_t * pHostapdState;
6048 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6049 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6050 const char *p2pMode = "DEV";
6051 const char *ccMode = "Standalone";
6052 int n;
6053
6054 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6055 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6056 {
6057 pAdapter = pAdapterNode->pAdapter;
6058 switch (pAdapter->device_mode) {
6059 case WLAN_HDD_INFRA_STATION:
6060 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6061 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6062 staChannel = pHddStaCtx->conn_info.operationChannel;
6063 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6064 }
6065 break;
6066 case WLAN_HDD_P2P_CLIENT:
6067 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6068 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6069 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6070 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6071 p2pMode = "CLI";
6072 }
6073 break;
6074 case WLAN_HDD_P2P_GO:
6075 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6076 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6077 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6078 p2pChannel = pHddApCtx->operatingChannel;
6079 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6080 }
6081 p2pMode = "GO";
6082 break;
6083 case WLAN_HDD_SOFTAP:
6084 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6085 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6086 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6087 apChannel = pHddApCtx->operatingChannel;
6088 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6089 }
6090 break;
6091 default:
6092 break;
6093 }
6094 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6095 pAdapterNode = pNext;
6096 }
6097 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6098 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6099 }
6100 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6101 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6102 if (p2pChannel > 0) {
6103 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6104 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6105 }
6106 if (apChannel > 0) {
6107 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6108 apChannel, MAC_ADDR_ARRAY(apBssid));
6109 }
6110
6111 if (p2pChannel > 0 && apChannel > 0) {
6112 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6113 }
6114}
6115
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006116bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006117{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006118 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006119}
6120
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006121/* Once SSR is disabled then it cannot be set. */
6122void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006123{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006124 if (HDD_SSR_DISABLED == isSsrRequired)
6125 return;
6126
Jeff Johnson295189b2012-06-20 16:38:30 -07006127 isSsrRequired = value;
6128}
6129
6130VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6131 hdd_adapter_list_node_t** ppAdapterNode)
6132{
6133 VOS_STATUS status;
6134 spin_lock(&pHddCtx->hddAdapters.lock);
6135 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6136 (hdd_list_node_t**) ppAdapterNode );
6137 spin_unlock(&pHddCtx->hddAdapters.lock);
6138 return status;
6139}
6140
6141VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6142 hdd_adapter_list_node_t* pAdapterNode,
6143 hdd_adapter_list_node_t** pNextAdapterNode)
6144{
6145 VOS_STATUS status;
6146 spin_lock(&pHddCtx->hddAdapters.lock);
6147 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6148 (hdd_list_node_t*) pAdapterNode,
6149 (hdd_list_node_t**)pNextAdapterNode );
6150
6151 spin_unlock(&pHddCtx->hddAdapters.lock);
6152 return status;
6153}
6154
6155VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6156 hdd_adapter_list_node_t* pAdapterNode)
6157{
6158 VOS_STATUS status;
6159 spin_lock(&pHddCtx->hddAdapters.lock);
6160 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6161 &pAdapterNode->node );
6162 spin_unlock(&pHddCtx->hddAdapters.lock);
6163 return status;
6164}
6165
6166VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6167 hdd_adapter_list_node_t** ppAdapterNode)
6168{
6169 VOS_STATUS status;
6170 spin_lock(&pHddCtx->hddAdapters.lock);
6171 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6172 (hdd_list_node_t**) ppAdapterNode );
6173 spin_unlock(&pHddCtx->hddAdapters.lock);
6174 return status;
6175}
6176
6177VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6178 hdd_adapter_list_node_t* pAdapterNode)
6179{
6180 VOS_STATUS status;
6181 spin_lock(&pHddCtx->hddAdapters.lock);
6182 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6183 (hdd_list_node_t*) pAdapterNode );
6184 spin_unlock(&pHddCtx->hddAdapters.lock);
6185 return status;
6186}
6187
6188VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6189 hdd_adapter_list_node_t* pAdapterNode)
6190{
6191 VOS_STATUS status;
6192 spin_lock(&pHddCtx->hddAdapters.lock);
6193 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6194 (hdd_list_node_t*) pAdapterNode );
6195 spin_unlock(&pHddCtx->hddAdapters.lock);
6196 return status;
6197}
6198
6199hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6200 tSirMacAddr macAddr )
6201{
6202 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6203 hdd_adapter_t *pAdapter;
6204 VOS_STATUS status;
6205
6206 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6207
6208 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6209 {
6210 pAdapter = pAdapterNode->pAdapter;
6211
6212 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6213 macAddr, sizeof(tSirMacAddr) ) )
6214 {
6215 return pAdapter;
6216 }
6217 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6218 pAdapterNode = pNext;
6219 }
6220
6221 return NULL;
6222
6223}
6224
6225hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6226{
6227 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6228 hdd_adapter_t *pAdapter;
6229 VOS_STATUS status;
6230
6231 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6232
6233 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6234 {
6235 pAdapter = pAdapterNode->pAdapter;
6236
6237 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6238 IFNAMSIZ ) )
6239 {
6240 return pAdapter;
6241 }
6242 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6243 pAdapterNode = pNext;
6244 }
6245
6246 return NULL;
6247
6248}
6249
6250hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6251{
6252 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6253 hdd_adapter_t *pAdapter;
6254 VOS_STATUS status;
6255
6256 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6257
6258 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6259 {
6260 pAdapter = pAdapterNode->pAdapter;
6261
6262 if( pAdapter && (mode == pAdapter->device_mode) )
6263 {
6264 return pAdapter;
6265 }
6266 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6267 pAdapterNode = pNext;
6268 }
6269
6270 return NULL;
6271
6272}
6273
6274//Remove this function later
6275hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6276{
6277 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6278 hdd_adapter_t *pAdapter;
6279 VOS_STATUS status;
6280
6281 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6282
6283 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6284 {
6285 pAdapter = pAdapterNode->pAdapter;
6286
6287 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6288 {
6289 return pAdapter;
6290 }
6291
6292 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6293 pAdapterNode = pNext;
6294 }
6295
6296 return NULL;
6297
6298}
6299
Jeff Johnson295189b2012-06-20 16:38:30 -07006300/**---------------------------------------------------------------------------
6301
6302 \brief hdd_set_monitor_tx_adapter() -
6303
6304 This API initializes the adapter to be used while transmitting on monitor
6305 adapter.
6306
6307 \param - pHddCtx - Pointer to the HDD context.
6308 pAdapter - Adapter that will used for TX. This can be NULL.
6309 \return - None.
6310 --------------------------------------------------------------------------*/
6311void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6312{
6313 hdd_adapter_t *pMonAdapter;
6314
6315 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6316
6317 if( NULL != pMonAdapter )
6318 {
6319 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6320 }
6321}
Jeff Johnson295189b2012-06-20 16:38:30 -07006322/**---------------------------------------------------------------------------
6323
6324 \brief hdd_select_queue() -
6325
6326 This API returns the operating channel of the requested device mode
6327
6328 \param - pHddCtx - Pointer to the HDD context.
6329 - mode - Device mode for which operating channel is required
6330 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6331 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6332 \return - channel number. "0" id the requested device is not found OR it is not connected.
6333 --------------------------------------------------------------------------*/
6334v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6335{
6336 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6337 VOS_STATUS status;
6338 hdd_adapter_t *pAdapter;
6339 v_U8_t operatingChannel = 0;
6340
6341 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6342
6343 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6344 {
6345 pAdapter = pAdapterNode->pAdapter;
6346
6347 if( mode == pAdapter->device_mode )
6348 {
6349 switch(pAdapter->device_mode)
6350 {
6351 case WLAN_HDD_INFRA_STATION:
6352 case WLAN_HDD_P2P_CLIENT:
6353 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6354 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6355 break;
6356 case WLAN_HDD_SOFTAP:
6357 case WLAN_HDD_P2P_GO:
6358 /*softap connection info */
6359 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6360 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6361 break;
6362 default:
6363 break;
6364 }
6365
6366 break; //Found the device of interest. break the loop
6367 }
6368
6369 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6370 pAdapterNode = pNext;
6371 }
6372 return operatingChannel;
6373}
6374
6375#ifdef WLAN_FEATURE_PACKET_FILTERING
6376/**---------------------------------------------------------------------------
6377
6378 \brief hdd_set_multicast_list() -
6379
6380 This used to set the multicast address list.
6381
6382 \param - dev - Pointer to the WLAN device.
6383 - skb - Pointer to OS packet (sk_buff).
6384 \return - success/fail
6385
6386 --------------------------------------------------------------------------*/
6387static void hdd_set_multicast_list(struct net_device *dev)
6388{
6389 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006390 int mc_count;
6391 int i = 0;
6392 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306393
6394 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006395 {
6396 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306397 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006398 return;
6399 }
6400
6401 if (dev->flags & IFF_ALLMULTI)
6402 {
6403 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006404 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306405 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006406 }
6407 else
6408 {
6409 mc_count = netdev_mc_count(dev);
6410 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006411 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006412 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6413 {
6414 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006415 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306416 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006417 return;
6418 }
6419
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306420 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006421
6422 netdev_for_each_mc_addr(ha, dev) {
6423 if (i == mc_count)
6424 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306425 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6426 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6427 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006428 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306429 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006430 i++;
6431 }
6432 }
6433 return;
6434}
6435#endif
6436
6437/**---------------------------------------------------------------------------
6438
6439 \brief hdd_select_queue() -
6440
6441 This function is registered with the Linux OS for network
6442 core to decide which queue to use first.
6443
6444 \param - dev - Pointer to the WLAN device.
6445 - skb - Pointer to OS packet (sk_buff).
6446 \return - ac, Queue Index/access category corresponding to UP in IP header
6447
6448 --------------------------------------------------------------------------*/
6449v_U16_t hdd_select_queue(struct net_device *dev,
6450 struct sk_buff *skb)
6451{
6452 return hdd_wmm_select_queue(dev, skb);
6453}
6454
6455
6456/**---------------------------------------------------------------------------
6457
6458 \brief hdd_wlan_initial_scan() -
6459
6460 This function triggers the initial scan
6461
6462 \param - pAdapter - Pointer to the HDD adapter.
6463
6464 --------------------------------------------------------------------------*/
6465void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6466{
6467 tCsrScanRequest scanReq;
6468 tCsrChannelInfo channelInfo;
6469 eHalStatus halStatus;
6470 unsigned long scanId;
6471 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6472
6473 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6474 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6475 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6476
6477 if(sme_Is11dSupported(pHddCtx->hHal))
6478 {
6479 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6480 if ( HAL_STATUS_SUCCESS( halStatus ) )
6481 {
6482 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6483 if( !scanReq.ChannelInfo.ChannelList )
6484 {
6485 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6486 vos_mem_free(channelInfo.ChannelList);
6487 return;
6488 }
6489 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6490 channelInfo.numOfChannels);
6491 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6492 vos_mem_free(channelInfo.ChannelList);
6493 }
6494
6495 scanReq.scanType = eSIR_PASSIVE_SCAN;
6496 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6497 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6498 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6499 }
6500 else
6501 {
6502 scanReq.scanType = eSIR_ACTIVE_SCAN;
6503 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6504 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6505 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6506 }
6507
6508 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6509 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6510 {
6511 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6512 __func__, halStatus );
6513 }
6514
6515 if(sme_Is11dSupported(pHddCtx->hHal))
6516 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6517}
6518
6519struct fullPowerContext
6520{
6521 struct completion completion;
6522 unsigned int magic;
6523};
6524#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6525
6526/**---------------------------------------------------------------------------
6527
6528 \brief hdd_full_power_callback() - HDD full power callback function
6529
6530 This is the function invoked by SME to inform the result of a full power
6531 request issued by HDD
6532
6533 \param - callbackcontext - Pointer to cookie
6534 \param - status - result of request
6535
6536 \return - None
6537
6538 --------------------------------------------------------------------------*/
6539static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6540{
6541 struct fullPowerContext *pContext = callbackContext;
6542
6543 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306544 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006545
6546 if (NULL == callbackContext)
6547 {
6548 hddLog(VOS_TRACE_LEVEL_ERROR,
6549 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006550 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006551 return;
6552 }
6553
6554 /* there is a race condition that exists between this callback function
6555 and the caller since the caller could time out either before or
6556 while this code is executing. we'll assume the timeout hasn't
6557 occurred, but we'll verify that right before we save our work */
6558
6559 if (POWER_CONTEXT_MAGIC != pContext->magic)
6560 {
6561 /* the caller presumably timed out so there is nothing we can do */
6562 hddLog(VOS_TRACE_LEVEL_WARN,
6563 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006564 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006565 return;
6566 }
6567
6568 /* the race is on. caller could have timed out immediately after
6569 we verified the magic, but if so, caller will wait a short time
6570 for us to notify the caller, so the context will stay valid */
6571 complete(&pContext->completion);
6572}
6573
6574/**---------------------------------------------------------------------------
6575
6576 \brief hdd_wlan_exit() - HDD WLAN exit function
6577
6578 This is the driver exit point (invoked during rmmod)
6579
6580 \param - pHddCtx - Pointer to the HDD Context
6581
6582 \return - None
6583
6584 --------------------------------------------------------------------------*/
6585void hdd_wlan_exit(hdd_context_t *pHddCtx)
6586{
6587 eHalStatus halStatus;
6588 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6589 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306590 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006591 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006592 struct fullPowerContext powerContext;
6593 long lrc;
6594
6595 ENTER();
6596
Jeff Johnson88ba7742013-02-27 14:36:02 -08006597 if (VOS_FTM_MODE != hdd_get_conparam())
6598 {
6599 // Unloading, restart logic is no more required.
6600 wlan_hdd_restart_deinit(pHddCtx);
6601 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006602
Jeff Johnson295189b2012-06-20 16:38:30 -07006603 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006604 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006605 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006606 {
6607 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6608 WLAN_HDD_INFRA_STATION);
6609 if (pAdapter == NULL)
6610 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6611
6612 if (pAdapter != NULL)
6613 {
6614 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6615 hdd_UnregisterWext(pAdapter->dev);
6616 }
6617 }
6618 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006619
Jeff Johnson295189b2012-06-20 16:38:30 -07006620 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006621 {
6622 wlan_hdd_ftm_close(pHddCtx);
6623 goto free_hdd_ctx;
6624 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006625 //Stop the Interface TX queue.
6626 //netif_tx_disable(pWlanDev);
6627 //netif_carrier_off(pWlanDev);
6628
Jeff Johnson295189b2012-06-20 16:38:30 -07006629 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6630 {
6631 pAdapter = hdd_get_adapter(pHddCtx,
6632 WLAN_HDD_SOFTAP);
6633 }
6634 else
6635 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006636 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006637 {
6638 pAdapter = hdd_get_adapter(pHddCtx,
6639 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006640 if (pAdapter == NULL)
6641 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006642 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006643 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006644 /* DeRegister with platform driver as client for Suspend/Resume */
6645 vosStatus = hddDeregisterPmOps(pHddCtx);
6646 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6647 {
6648 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6649 VOS_ASSERT(0);
6650 }
6651
6652 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6653 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6654 {
6655 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6656 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006657
6658 // Cancel any outstanding scan requests. We are about to close all
6659 // of our adapters, but an adapter structure is what SME passes back
6660 // to our callback function. Hence if there are any outstanding scan
6661 // requests then there is a race condition between when the adapter
6662 // is closed and when the callback is invoked. We try to resolve that
6663 // race condition here by canceling any outstanding scans before we
6664 // close the adapters.
6665 // Note that the scans may be cancelled in an asynchronous manner, so
6666 // ideally there needs to be some kind of synchronization. Rather than
6667 // introduce a new synchronization here, we will utilize the fact that
6668 // we are about to Request Full Power, and since that is synchronized,
6669 // the expectation is that by the time Request Full Power has completed,
6670 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006671 if (NULL != pAdapter)
6672 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6673 else
6674 hddLog(VOS_TRACE_LEVEL_ERROR,
6675 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006676
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006677 //Stop the traffic monitor timer
6678 if ( VOS_TIMER_STATE_RUNNING ==
6679 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6680 {
6681 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6682 }
6683
6684 // Destroy the traffic monitor timer
6685 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
6686 &pHddCtx->tx_rx_trafficTmr)))
6687 {
6688 hddLog(VOS_TRACE_LEVEL_ERROR,
6689 "%s: Cannot deallocate Traffic monitor timer", __func__);
6690 }
6691
Jeff Johnson295189b2012-06-20 16:38:30 -07006692 //Disable IMPS/BMPS as we do not want the device to enter any power
6693 //save mode during shutdown
6694 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6695 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6696 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
6697
6698 //Ensure that device is in full power as we will touch H/W during vos_Stop
6699 init_completion(&powerContext.completion);
6700 powerContext.magic = POWER_CONTEXT_MAGIC;
6701
6702 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
6703 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
6704
6705 if (eHAL_STATUS_SUCCESS != halStatus)
6706 {
6707 if (eHAL_STATUS_PMC_PENDING == halStatus)
6708 {
6709 /* request was sent -- wait for the response */
6710 lrc = wait_for_completion_interruptible_timeout(
6711 &powerContext.completion,
6712 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
6713 /* either we have a response or we timed out
6714 either way, first invalidate our magic */
6715 powerContext.magic = 0;
6716 if (lrc <= 0)
6717 {
6718 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006719 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07006720 /* there is a race condition such that the callback
6721 function could be executing at the same time we are. of
6722 primary concern is if the callback function had already
6723 verified the "magic" but hasn't yet set the completion
6724 variable. Since the completion variable is on our
6725 stack, we'll delay just a bit to make sure the data is
6726 still valid if that is the case */
6727 msleep(50);
6728 }
6729 }
6730 else
6731 {
6732 hddLog(VOS_TRACE_LEVEL_ERROR,
6733 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006734 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07006735 VOS_ASSERT(0);
6736 /* continue -- need to clean up as much as possible */
6737 }
6738 }
6739
Yue Ma0d4891e2013-08-06 17:01:45 -07006740 hdd_debugfs_exit(pHddCtx);
6741
Jeff Johnson295189b2012-06-20 16:38:30 -07006742 // Unregister the Net Device Notifier
6743 unregister_netdevice_notifier(&hdd_netdev_notifier);
6744
Jeff Johnson295189b2012-06-20 16:38:30 -07006745 hdd_stop_all_adapters( pHddCtx );
6746
Jeff Johnson295189b2012-06-20 16:38:30 -07006747#ifdef WLAN_BTAMP_FEATURE
6748 vosStatus = WLANBAP_Stop(pVosContext);
6749 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6750 {
6751 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
6752 "%s: Failed to stop BAP",__func__);
6753 }
6754#endif //WLAN_BTAMP_FEATURE
6755
6756 //Stop all the modules
6757 vosStatus = vos_stop( pVosContext );
6758 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6759 {
6760 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6761 "%s: Failed to stop VOSS",__func__);
6762 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6763 }
6764
Jeff Johnson295189b2012-06-20 16:38:30 -07006765 //Assert Deep sleep signal now to put Libra HW in lowest power state
6766 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6767 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6768
6769 //Vote off any PMIC voltage supplies
6770 vos_chipPowerDown(NULL, NULL, NULL);
6771
6772 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
6773
Leo Chang59cdc7e2013-07-10 10:08:21 -07006774
Jeff Johnson295189b2012-06-20 16:38:30 -07006775 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07006776 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006777
6778 //Close the scheduler before calling vos_close to make sure no thread is
6779 // scheduled after the each module close is called i.e after all the data
6780 // structures are freed.
6781 vosStatus = vos_sched_close( pVosContext );
6782 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
6783 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6784 "%s: Failed to close VOSS Scheduler",__func__);
6785 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6786 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006787#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006788#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6789 /* Destroy the wake lock */
6790 wake_lock_destroy(&pHddCtx->rx_wake_lock);
6791#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006792 /* Destroy the wake lock */
6793 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006794#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006795
6796 //Close VOSS
6797 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
6798 vos_close(pVosContext);
6799
Jeff Johnson295189b2012-06-20 16:38:30 -07006800 //Close Watchdog
6801 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6802 vos_watchdog_close(pVosContext);
6803
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306804 //Clean up HDD Nlink Service
6805 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07006806#ifdef WLAN_KD_READY_NOTIFIER
6807 nl_srv_exit(pHddCtx->ptt_pid);
6808#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306809 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006810#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306811
Jeff Johnson295189b2012-06-20 16:38:30 -07006812 /* Cancel the vote for XO Core ON.
6813 * This is done here to ensure there is no race condition since MC, TX and WD threads have
6814 * exited at this point
6815 */
6816 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
6817 " when WLAN is turned OFF\n");
6818 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6819 {
6820 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
6821 " Not returning failure."
6822 " Power consumed will be high\n");
6823 }
6824
6825 hdd_close_all_adapters( pHddCtx );
6826
6827
6828 //Free up dynamically allocated members inside HDD Adapter
6829 kfree(pHddCtx->cfg_ini);
6830 pHddCtx->cfg_ini= NULL;
6831
6832 /* free the power on lock from platform driver */
6833 if (free_riva_power_on_lock("wlan"))
6834 {
6835 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
6836 __func__);
6837 }
6838
Jeff Johnson88ba7742013-02-27 14:36:02 -08006839free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07006840 /* FTM mode, WIPHY did not registered
6841 If un-register here, system crash will happen */
6842 if (VOS_FTM_MODE != hdd_get_conparam())
6843 {
6844 wiphy_unregister(wiphy) ;
6845 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006846 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006847 if (hdd_is_ssr_required())
6848 {
6849 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07006850 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07006851 msleep(5000);
6852 }
6853 hdd_set_ssr_required (VOS_FALSE);
6854}
6855
6856
6857/**---------------------------------------------------------------------------
6858
6859 \brief hdd_update_config_from_nv() - Function to update the contents of
6860 the running configuration with parameters taken from NV storage
6861
6862 \param - pHddCtx - Pointer to the HDD global context
6863
6864 \return - VOS_STATUS_SUCCESS if successful
6865
6866 --------------------------------------------------------------------------*/
6867static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
6868{
Jeff Johnson295189b2012-06-20 16:38:30 -07006869 v_BOOL_t itemIsValid = VOS_FALSE;
6870 VOS_STATUS status;
6871 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
6872 v_U8_t macLoop;
6873
6874 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
6875 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
6876 if(status != VOS_STATUS_SUCCESS)
6877 {
6878 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
6879 return VOS_STATUS_E_FAILURE;
6880 }
6881
6882 if (itemIsValid == VOS_TRUE)
6883 {
6884 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
6885 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
6886 VOS_MAX_CONCURRENCY_PERSONA);
6887 if(status != VOS_STATUS_SUCCESS)
6888 {
6889 /* Get MAC from NV fail, not update CFG info
6890 * INI MAC value will be used for MAC setting */
6891 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
6892 return VOS_STATUS_E_FAILURE;
6893 }
6894
6895 /* If first MAC is not valid, treat all others are not valid
6896 * Then all MACs will be got from ini file */
6897 if(vos_is_macaddr_zero(&macFromNV[0]))
6898 {
6899 /* MAC address in NV file is not configured yet */
6900 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
6901 return VOS_STATUS_E_INVAL;
6902 }
6903
6904 /* Get MAC address from NV, update CFG info */
6905 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
6906 {
6907 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
6908 {
6909 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
6910 /* This MAC is not valid, skip it
6911 * This MAC will be got from ini file */
6912 }
6913 else
6914 {
6915 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
6916 (v_U8_t *)&macFromNV[macLoop].bytes[0],
6917 VOS_MAC_ADDR_SIZE);
6918 }
6919 }
6920 }
6921 else
6922 {
6923 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
6924 return VOS_STATUS_E_FAILURE;
6925 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006926
Jeff Johnson295189b2012-06-20 16:38:30 -07006927
6928 return VOS_STATUS_SUCCESS;
6929}
6930
6931/**---------------------------------------------------------------------------
6932
6933 \brief hdd_post_voss_start_config() - HDD post voss start config helper
6934
6935 \param - pAdapter - Pointer to the HDD
6936
6937 \return - None
6938
6939 --------------------------------------------------------------------------*/
6940VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
6941{
6942 eHalStatus halStatus;
6943 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306944 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07006945
Jeff Johnson295189b2012-06-20 16:38:30 -07006946
6947 // Send ready indication to the HDD. This will kick off the MAC
6948 // into a 'running' state and should kick off an initial scan.
6949 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
6950 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6951 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306952 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07006953 "code %08d [x%08x]",__func__, halStatus, halStatus );
6954 return VOS_STATUS_E_FAILURE;
6955 }
6956
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306957 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07006958 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
6959 // And RIVA will crash
6960 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
6961 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306962 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
6963 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
6964
6965
Jeff Johnson295189b2012-06-20 16:38:30 -07006966 return VOS_STATUS_SUCCESS;
6967}
6968
Jeff Johnson295189b2012-06-20 16:38:30 -07006969/* wake lock APIs for HDD */
6970void hdd_prevent_suspend(void)
6971{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006972#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006973 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006974#else
6975 wcnss_prevent_suspend();
6976#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006977}
6978
6979void hdd_allow_suspend(void)
6980{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006981#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07006982 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07006983#else
6984 wcnss_allow_suspend();
6985#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006986}
6987
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07006988void hdd_allow_suspend_timeout(v_U32_t timeout)
6989{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006990#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07006991 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07006992#else
6993 /* Do nothing as there is no API in wcnss for timeout*/
6994#endif
6995}
6996
Jeff Johnson295189b2012-06-20 16:38:30 -07006997/**---------------------------------------------------------------------------
6998
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07006999 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7000 information between Host and Riva
7001
7002 This function gets reported version of FW
7003 It also finds the version of Riva headers used to compile the host
7004 It compares the above two and prints a warning if they are different
7005 It gets the SW and HW version string
7006 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7007 indicating the features they support through a bitmap
7008
7009 \param - pHddCtx - Pointer to HDD context
7010
7011 \return - void
7012
7013 --------------------------------------------------------------------------*/
7014
7015void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7016{
7017
7018 tSirVersionType versionCompiled;
7019 tSirVersionType versionReported;
7020 tSirVersionString versionString;
7021 tANI_U8 fwFeatCapsMsgSupported = 0;
7022 VOS_STATUS vstatus;
7023
7024 /* retrieve and display WCNSS version information */
7025 do {
7026
7027 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7028 &versionCompiled);
7029 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7030 {
7031 hddLog(VOS_TRACE_LEVEL_FATAL,
7032 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007033 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007034 break;
7035 }
7036
7037 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7038 &versionReported);
7039 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7040 {
7041 hddLog(VOS_TRACE_LEVEL_FATAL,
7042 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007043 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007044 break;
7045 }
7046
7047 if ((versionCompiled.major != versionReported.major) ||
7048 (versionCompiled.minor != versionReported.minor) ||
7049 (versionCompiled.version != versionReported.version) ||
7050 (versionCompiled.revision != versionReported.revision))
7051 {
7052 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7053 "Host expected %u.%u.%u.%u\n",
7054 WLAN_MODULE_NAME,
7055 (int)versionReported.major,
7056 (int)versionReported.minor,
7057 (int)versionReported.version,
7058 (int)versionReported.revision,
7059 (int)versionCompiled.major,
7060 (int)versionCompiled.minor,
7061 (int)versionCompiled.version,
7062 (int)versionCompiled.revision);
7063 }
7064 else
7065 {
7066 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7067 WLAN_MODULE_NAME,
7068 (int)versionReported.major,
7069 (int)versionReported.minor,
7070 (int)versionReported.version,
7071 (int)versionReported.revision);
7072 }
7073
7074 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7075 versionString,
7076 sizeof(versionString));
7077 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7078 {
7079 hddLog(VOS_TRACE_LEVEL_FATAL,
7080 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007081 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007082 break;
7083 }
7084
7085 pr_info("%s: WCNSS software version %s\n",
7086 WLAN_MODULE_NAME, versionString);
7087
7088 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7089 versionString,
7090 sizeof(versionString));
7091 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7092 {
7093 hddLog(VOS_TRACE_LEVEL_FATAL,
7094 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007095 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007096 break;
7097 }
7098
7099 pr_info("%s: WCNSS hardware version %s\n",
7100 WLAN_MODULE_NAME, versionString);
7101
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007102 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7103 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007104 send the message only if it the riva is 1.1
7105 minor numbers for different riva branches:
7106 0 -> (1.0)Mainline Build
7107 1 -> (1.1)Mainline Build
7108 2->(1.04) Stability Build
7109 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007110 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007111 ((versionReported.minor>=1) && (versionReported.version>=1)))
7112 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7113 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007114
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007115 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007116 {
7117#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7118 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7119 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7120#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007121 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7122 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7123 {
7124 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7125 }
7126
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007127 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007128 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007129
7130 } while (0);
7131
7132}
7133
7134/**---------------------------------------------------------------------------
7135
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307136 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7137
7138 \param - pHddCtx - Pointer to the hdd context
7139
7140 \return - true if hardware supports 5GHz
7141
7142 --------------------------------------------------------------------------*/
7143static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7144{
7145 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7146 * then hardware support 5Ghz.
7147 */
7148 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7149 {
7150 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7151 return true;
7152 }
7153 else
7154 {
7155 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7156 __func__);
7157 return false;
7158 }
7159}
7160
7161
7162/**---------------------------------------------------------------------------
7163
Jeff Johnson295189b2012-06-20 16:38:30 -07007164 \brief hdd_wlan_startup() - HDD init function
7165
7166 This is the driver startup code executed once a WLAN device has been detected
7167
7168 \param - dev - Pointer to the underlying device
7169
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007170 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007171
7172 --------------------------------------------------------------------------*/
7173
7174int hdd_wlan_startup(struct device *dev )
7175{
7176 VOS_STATUS status;
7177 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007178 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007179 hdd_context_t *pHddCtx = NULL;
7180 v_CONTEXT_t pVosContext= NULL;
7181#ifdef WLAN_BTAMP_FEATURE
7182 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7183 WLANBAP_ConfigType btAmpConfig;
7184 hdd_config_t *pConfig;
7185#endif
7186 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007187 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007188
7189 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007190 /*
7191 * cfg80211: wiphy allocation
7192 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307193 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007194
7195 if(wiphy == NULL)
7196 {
7197 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007198 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007199 }
7200
7201 pHddCtx = wiphy_priv(wiphy);
7202
Jeff Johnson295189b2012-06-20 16:38:30 -07007203 //Initialize the adapter context to zeros.
7204 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7205
Jeff Johnson295189b2012-06-20 16:38:30 -07007206 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007207 hdd_prevent_suspend();
7208 pHddCtx->isLoadUnloadInProgress = TRUE;
7209
7210 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7211
7212 /*Get vos context here bcoz vos_open requires it*/
7213 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7214
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007215 if(pVosContext == NULL)
7216 {
7217 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7218 goto err_free_hdd_context;
7219 }
7220
Jeff Johnson295189b2012-06-20 16:38:30 -07007221 //Save the Global VOSS context in adapter context for future.
7222 pHddCtx->pvosContext = pVosContext;
7223
7224 //Save the adapter context in global context for future.
7225 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7226
Jeff Johnson295189b2012-06-20 16:38:30 -07007227 pHddCtx->parent_dev = dev;
7228
7229 init_completion(&pHddCtx->full_pwr_comp_var);
7230 init_completion(&pHddCtx->standby_comp_var);
7231 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007232 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007233 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Amar Singhala49cbc52013-10-08 18:37:44 -07007234
7235#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007236 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007237#else
7238 init_completion(&pHddCtx->driver_crda_req);
7239#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007240
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307241 spin_lock_init(&pHddCtx->schedScan_lock);
7242
Jeff Johnson295189b2012-06-20 16:38:30 -07007243 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7244
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307245#ifdef FEATURE_WLAN_TDLS
7246 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7247 * invoked by other instances also) to protect the concurrent
7248 * access for the Adapters by TDLS module.
7249 */
7250 mutex_init(&pHddCtx->tdls_lock);
7251#endif
7252
Jeff Johnson295189b2012-06-20 16:38:30 -07007253 // Load all config first as TL config is needed during vos_open
7254 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7255 if(pHddCtx->cfg_ini == NULL)
7256 {
7257 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7258 goto err_free_hdd_context;
7259 }
7260
7261 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7262
7263 // Read and parse the qcom_cfg.ini file
7264 status = hdd_parse_config_ini( pHddCtx );
7265 if ( VOS_STATUS_SUCCESS != status )
7266 {
7267 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7268 __func__, WLAN_INI_FILE);
7269 goto err_config;
7270 }
7271
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307272 /* INI has been read, initialise the configuredMcastBcastFilter with
7273 * INI value as this will serve as the default value
7274 */
7275 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7276 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7277 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307278
7279 if (false == hdd_is_5g_supported(pHddCtx))
7280 {
7281 //5Ghz is not supported.
7282 if (1 != pHddCtx->cfg_ini->nBandCapability)
7283 {
7284 hddLog(VOS_TRACE_LEVEL_INFO,
7285 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7286 pHddCtx->cfg_ini->nBandCapability = 1;
7287 }
7288 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307289
7290 /* If SNR Monitoring is enabled, FW has to parse all beacons
7291 * for calcaluting and storing the average SNR, so set Nth beacon
7292 * filter to 1 to enable FW to parse all the beaocons
7293 */
7294 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7295 {
7296 /* The log level is deliberately set to WARN as overriding
7297 * nthBeaconFilter to 1 will increase power cosumption and this
7298 * might just prove helpful to detect the power issue.
7299 */
7300 hddLog(VOS_TRACE_LEVEL_WARN,
7301 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7302 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7303 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007304 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307305 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007306 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307307 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007308 {
7309 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307310 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7311 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007312 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007313
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007314 // Update VOS trace levels based upon the cfg.ini
7315 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7316 pHddCtx->cfg_ini->vosTraceEnableBAP);
7317 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7318 pHddCtx->cfg_ini->vosTraceEnableTL);
7319 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7320 pHddCtx->cfg_ini->vosTraceEnableWDI);
7321 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7322 pHddCtx->cfg_ini->vosTraceEnableHDD);
7323 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7324 pHddCtx->cfg_ini->vosTraceEnableSME);
7325 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7326 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307327 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7328 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007329 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7330 pHddCtx->cfg_ini->vosTraceEnableWDA);
7331 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7332 pHddCtx->cfg_ini->vosTraceEnableSYS);
7333 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7334 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007335 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7336 pHddCtx->cfg_ini->vosTraceEnableSAP);
7337 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7338 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007339
Jeff Johnson295189b2012-06-20 16:38:30 -07007340 // Update WDI trace levels based upon the cfg.ini
7341 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7342 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7343 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7344 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7345 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7346 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7347 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7348 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007349
Jeff Johnson88ba7742013-02-27 14:36:02 -08007350 if (VOS_FTM_MODE == hdd_get_conparam())
7351 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007352 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7353 {
7354 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7355 goto err_free_hdd_context;
7356 }
7357 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7358 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007359 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007360
Jeff Johnson88ba7742013-02-27 14:36:02 -08007361 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007362 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7363 {
7364 status = vos_watchdog_open(pVosContext,
7365 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7366
7367 if(!VOS_IS_STATUS_SUCCESS( status ))
7368 {
7369 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307370 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007371 }
7372 }
7373
7374 pHddCtx->isLogpInProgress = FALSE;
7375 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7376
Jeff Johnson295189b2012-06-20 16:38:30 -07007377 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7378 if(!VOS_IS_STATUS_SUCCESS(status))
7379 {
7380 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007381 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007382 }
7383
Amar Singhala49cbc52013-10-08 18:37:44 -07007384#ifdef CONFIG_ENABLE_LINUX_REG
7385 /* registration of wiphy dev with cfg80211 */
7386 if (0 > wlan_hdd_cfg80211_register(wiphy))
7387 {
7388 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7389 goto err_clkvote;
7390 }
7391#endif
7392
Jeff Johnson295189b2012-06-20 16:38:30 -07007393 status = vos_open( &pVosContext, 0);
7394 if ( !VOS_IS_STATUS_SUCCESS( status ))
7395 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007396 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007397 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007398 }
7399
Jeff Johnson295189b2012-06-20 16:38:30 -07007400 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7401
7402 if ( NULL == pHddCtx->hHal )
7403 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007404 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007405 goto err_vosclose;
7406 }
7407
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007408 status = vos_preStart( pHddCtx->pvosContext );
7409 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7410 {
7411 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7412 goto err_vosclose;
7413 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007414
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007415 /* Note that the vos_preStart() sequence triggers the cfg download.
7416 The cfg download must occur before we update the SME config
7417 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007418 status = hdd_set_sme_config( pHddCtx );
7419
7420 if ( VOS_STATUS_SUCCESS != status )
7421 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007422 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7423 goto err_vosclose;
7424 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007425
7426 //Initialize the WMM module
7427 status = hdd_wmm_init(pHddCtx);
7428 if (!VOS_IS_STATUS_SUCCESS(status))
7429 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007430 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007431 goto err_vosclose;
7432 }
7433
Jeff Johnson295189b2012-06-20 16:38:30 -07007434 /* In the integrated architecture we update the configuration from
7435 the INI file and from NV before vOSS has been started so that
7436 the final contents are available to send down to the cCPU */
7437
7438 // Apply the cfg.ini to cfg.dat
7439 if (FALSE == hdd_update_config_dat(pHddCtx))
7440 {
7441 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7442 goto err_vosclose;
7443 }
7444
7445 // Apply the NV to cfg.dat
7446 /* Prima Update MAC address only at here */
7447 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7448 {
7449#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7450 /* There was not a valid set of MAC Addresses in NV. See if the
7451 default addresses were modified by the cfg.ini settings. If so,
7452 we'll use them, but if not, we'll autogenerate a set of MAC
7453 addresses based upon the device serial number */
7454
7455 static const v_MACADDR_t default_address =
7456 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7457 unsigned int serialno;
7458 int i;
7459
7460 serialno = wcnss_get_serial_number();
7461 if ((0 != serialno) &&
7462 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7463 sizeof(default_address))))
7464 {
7465 /* cfg.ini has the default address, invoke autogen logic */
7466
7467 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7468 bytes of the serial number that can be used to generate
7469 the other 3 bytes of the MAC address. Mask off all but
7470 the lower 3 bytes (this will also make sure we don't
7471 overflow in the next step) */
7472 serialno &= 0x00FFFFFF;
7473
7474 /* we need a unique address for each session */
7475 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7476
7477 /* autogen all addresses */
7478 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7479 {
7480 /* start with the entire default address */
7481 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7482 /* then replace the lower 3 bytes */
7483 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7484 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7485 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7486
7487 serialno++;
7488 }
7489
7490 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7491 MAC_ADDRESS_STR,
7492 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7493 }
7494 else
7495#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7496 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007497 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007498 "%s: Invalid MAC address in NV, using MAC from ini file "
7499 MAC_ADDRESS_STR, __func__,
7500 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7501 }
7502 }
7503 {
7504 eHalStatus halStatus;
7505 // Set the MAC Address
7506 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7507 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7508 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7509 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7510
7511 if (!HAL_STATUS_SUCCESS( halStatus ))
7512 {
7513 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7514 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007515 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007516 }
7517 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007518
7519 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7520 Note: Firmware image will be read and downloaded inside vos_start API */
7521 status = vos_start( pHddCtx->pvosContext );
7522 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7523 {
7524 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7525 goto err_vosclose;
7526 }
7527
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007528 /* Exchange capability info between Host and FW and also get versioning info from FW */
7529 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007530
7531 status = hdd_post_voss_start_config( pHddCtx );
7532 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7533 {
7534 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7535 __func__);
7536 goto err_vosstop;
7537 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007538
7539#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307540 wlan_hdd_cfg80211_update_reg_info( wiphy );
7541
7542 /* registration of wiphy dev with cfg80211 */
7543 if (0 > wlan_hdd_cfg80211_register(wiphy))
7544 {
7545 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7546 goto err_vosstop;
7547 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007548#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007549
Jeff Johnson295189b2012-06-20 16:38:30 -07007550 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7551 {
7552 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7553 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7554 }
7555 else
7556 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007557 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7558 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7559 if (pAdapter != NULL)
7560 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307561 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007562 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307563 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7564 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7565 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007566
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307567 /* Generate the P2P Device Address. This consists of the device's
7568 * primary MAC address with the locally administered bit set.
7569 */
7570 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007571 }
7572 else
7573 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307574 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7575 if (p2p_dev_addr != NULL)
7576 {
7577 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7578 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7579 }
7580 else
7581 {
7582 hddLog(VOS_TRACE_LEVEL_FATAL,
7583 "%s: Failed to allocate mac_address for p2p_device",
7584 __func__);
7585 goto err_close_adapter;
7586 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007587 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007588
7589 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7590 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7591 if ( NULL == pP2pAdapter )
7592 {
7593 hddLog(VOS_TRACE_LEVEL_FATAL,
7594 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007595 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007596 goto err_close_adapter;
7597 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007598 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007599 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007600
7601 if( pAdapter == NULL )
7602 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007603 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7604 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007605 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007606
Jeff Johnson295189b2012-06-20 16:38:30 -07007607#ifdef WLAN_BTAMP_FEATURE
7608 vStatus = WLANBAP_Open(pVosContext);
7609 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7610 {
7611 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7612 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007613 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007614 }
7615
7616 vStatus = BSL_Init(pVosContext);
7617 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7618 {
7619 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7620 "%s: Failed to Init BSL",__func__);
7621 goto err_bap_close;
7622 }
7623 vStatus = WLANBAP_Start(pVosContext);
7624 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7625 {
7626 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7627 "%s: Failed to start TL",__func__);
7628 goto err_bap_close;
7629 }
7630
7631 pConfig = pHddCtx->cfg_ini;
7632 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7633 status = WLANBAP_SetConfig(&btAmpConfig);
7634
7635#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007636
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007637#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7638 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7639 {
7640 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7641 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7642 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7643 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7644 }
7645#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007646#ifdef FEATURE_WLAN_SCAN_PNO
7647 /*SME must send channel update configuration to RIVA*/
7648 sme_UpdateChannelConfig(pHddCtx->hHal);
7649#endif
7650
Jeff Johnson295189b2012-06-20 16:38:30 -07007651 /* Register with platform driver as client for Suspend/Resume */
7652 status = hddRegisterPmOps(pHddCtx);
7653 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7654 {
7655 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7656#ifdef WLAN_BTAMP_FEATURE
7657 goto err_bap_stop;
7658#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007659 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007660#endif //WLAN_BTAMP_FEATURE
7661 }
7662
Yue Ma0d4891e2013-08-06 17:01:45 -07007663 /* Open debugfs interface */
7664 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
7665 {
7666 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7667 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07007668 }
7669
Jeff Johnson295189b2012-06-20 16:38:30 -07007670 /* Register TM level change handler function to the platform */
7671 status = hddDevTmRegisterNotifyCallback(pHddCtx);
7672 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7673 {
7674 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
7675 goto err_unregister_pmops;
7676 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007677
7678 /* register for riva power on lock to platform driver */
7679 if (req_riva_power_on_lock("wlan"))
7680 {
7681 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
7682 __func__);
7683 goto err_unregister_pmops;
7684 }
7685
Jeff Johnson295189b2012-06-20 16:38:30 -07007686 // register net device notifier for device change notification
7687 ret = register_netdevice_notifier(&hdd_netdev_notifier);
7688
7689 if(ret < 0)
7690 {
7691 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
7692 goto err_free_power_on_lock;
7693 }
7694
7695 //Initialize the nlink service
7696 if(nl_srv_init() != 0)
7697 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307698 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007699 goto err_reg_netdev;
7700 }
7701
7702 //Initialize the BTC service
7703 if(btc_activate_service(pHddCtx) != 0)
7704 {
7705 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
7706 goto err_nl_srv;
7707 }
7708
7709#ifdef PTT_SOCK_SVC_ENABLE
7710 //Initialize the PTT service
7711 if(ptt_sock_activate_svc(pHddCtx) != 0)
7712 {
7713 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
7714 goto err_nl_srv;
7715 }
7716#endif
7717
Jeff Johnson295189b2012-06-20 16:38:30 -07007718 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007719 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007720 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07007721 /* Action frame registered in one adapter which will
7722 * applicable to all interfaces
7723 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07007724 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007725 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007726
7727 mutex_init(&pHddCtx->sap_lock);
7728
7729 pHddCtx->isLoadUnloadInProgress = FALSE;
7730
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007731#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007732#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7733 /* Initialize the wake lcok */
7734 wake_lock_init(&pHddCtx->rx_wake_lock,
7735 WAKE_LOCK_SUSPEND,
7736 "qcom_rx_wakelock");
7737#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007738 /* Initialize the wake lcok */
7739 wake_lock_init(&pHddCtx->sap_wake_lock,
7740 WAKE_LOCK_SUSPEND,
7741 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007742#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007743
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007744 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
7745 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07007746
7747 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7748 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05307749
Jeff Johnsone7245742012-09-05 17:12:55 -07007750 // Initialize the restart logic
7751 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05307752
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007753 //Register the traffic monitor timer now
7754 if ( pHddCtx->cfg_ini->dynSplitscan)
7755 {
7756 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
7757 VOS_TIMER_TYPE_SW,
7758 hdd_tx_rx_pkt_cnt_stat_timer_handler,
7759 (void *)pHddCtx);
7760 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007761 goto success;
7762
7763err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07007764#ifdef WLAN_KD_READY_NOTIFIER
7765 nl_srv_exit(pHddCtx->ptt_pid);
7766#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007767 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007768#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07007769err_reg_netdev:
7770 unregister_netdevice_notifier(&hdd_netdev_notifier);
7771
7772err_free_power_on_lock:
7773 free_riva_power_on_lock("wlan");
7774
7775err_unregister_pmops:
7776 hddDevTmUnregisterNotifyCallback(pHddCtx);
7777 hddDeregisterPmOps(pHddCtx);
7778
Yue Ma0d4891e2013-08-06 17:01:45 -07007779 hdd_debugfs_exit(pHddCtx);
7780
Jeff Johnson295189b2012-06-20 16:38:30 -07007781#ifdef WLAN_BTAMP_FEATURE
7782err_bap_stop:
7783 WLANBAP_Stop(pVosContext);
7784#endif
7785
7786#ifdef WLAN_BTAMP_FEATURE
7787err_bap_close:
7788 WLANBAP_Close(pVosContext);
7789#endif
7790
Jeff Johnson295189b2012-06-20 16:38:30 -07007791err_close_adapter:
7792 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07007793
7794#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307795 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07007796#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007797
7798err_vosstop:
7799 vos_stop(pVosContext);
7800
Amar Singhala49cbc52013-10-08 18:37:44 -07007801err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07007802 status = vos_sched_close( pVosContext );
7803 if (!VOS_IS_STATUS_SUCCESS(status)) {
7804 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7805 "%s: Failed to close VOSS Scheduler", __func__);
7806 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
7807 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007808 vos_close(pVosContext );
7809
7810err_wiphy_unregister:
7811
7812#ifdef CONFIG_ENABLE_LINUX_REG
7813 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07007814
Jeff Johnson295189b2012-06-20 16:38:30 -07007815err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07007816#endif
7817
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007818 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007819
7820err_wdclose:
7821 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7822 vos_watchdog_close(pVosContext);
7823
Jeff Johnson295189b2012-06-20 16:38:30 -07007824err_config:
7825 kfree(pHddCtx->cfg_ini);
7826 pHddCtx->cfg_ini= NULL;
7827
7828err_free_hdd_context:
7829 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07007830 wiphy_free(wiphy) ;
7831 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007832 VOS_BUG(1);
7833
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08007834 if (hdd_is_ssr_required())
7835 {
7836 /* WDI timeout had happened during load, so SSR is needed here */
7837 subsystem_restart("wcnss");
7838 msleep(5000);
7839 }
7840 hdd_set_ssr_required (VOS_FALSE);
7841
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007842 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007843
7844success:
7845 EXIT();
7846 return 0;
7847}
7848
7849/**---------------------------------------------------------------------------
7850
Jeff Johnson32d95a32012-09-10 13:15:23 -07007851 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07007852
Jeff Johnson32d95a32012-09-10 13:15:23 -07007853 This is the driver entry point - called in different timeline depending
7854 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07007855
7856 \param - None
7857
7858 \return - 0 for success, non zero for failure
7859
7860 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07007861static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007862{
7863 VOS_STATUS status;
7864 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007865 struct device *dev = NULL;
7866 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007867#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7868 int max_retries = 0;
7869#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007870
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307871#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7872 vos_wconn_trace_init();
7873#endif
7874
Jeff Johnson295189b2012-06-20 16:38:30 -07007875 ENTER();
7876
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007877#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007878 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07007879#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007880
7881 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
7882 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
7883
7884 //Power Up Libra WLAN card first if not already powered up
7885 status = vos_chipPowerUp(NULL,NULL,NULL);
7886 if (!VOS_IS_STATUS_SUCCESS(status))
7887 {
7888 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
7889 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307890#ifdef WLAN_OPEN_SOURCE
7891 wake_lock_destroy(&wlan_wake_lock);
7892#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007893 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007894 }
7895
Jeff Johnson295189b2012-06-20 16:38:30 -07007896#ifdef ANI_BUS_TYPE_PCI
7897
7898 dev = wcnss_wlan_get_device();
7899
7900#endif // ANI_BUS_TYPE_PCI
7901
7902#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007903
7904#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7905 /* wait until WCNSS driver downloads NV */
7906 while (!wcnss_device_ready() && 5 >= ++max_retries) {
7907 msleep(1000);
7908 }
7909 if (max_retries >= 5) {
7910 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307911#ifdef WLAN_OPEN_SOURCE
7912 wake_lock_destroy(&wlan_wake_lock);
7913#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007914 return -ENODEV;
7915 }
7916#endif
7917
Jeff Johnson295189b2012-06-20 16:38:30 -07007918 dev = wcnss_wlan_get_device();
7919#endif // ANI_BUS_TYPE_PLATFORM
7920
7921
7922 do {
7923 if (NULL == dev) {
7924 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
7925 ret_status = -1;
7926 break;
7927 }
7928
7929#ifdef MEMORY_DEBUG
7930 vos_mem_init();
7931#endif
7932
7933#ifdef TIMER_MANAGER
7934 vos_timer_manager_init();
7935#endif
7936
7937 /* Preopen VOSS so that it is ready to start at least SAL */
7938 status = vos_preOpen(&pVosContext);
7939
7940 if (!VOS_IS_STATUS_SUCCESS(status))
7941 {
7942 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
7943 ret_status = -1;
7944 break;
7945 }
7946
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07007947#ifndef MODULE
7948 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
7949 */
7950 hdd_set_conparam((v_UINT_t)con_mode);
7951#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007952
7953 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007954 if (hdd_wlan_startup(dev))
7955 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007956 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007957 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007958 vos_preClose( &pVosContext );
7959 ret_status = -1;
7960 break;
7961 }
7962
7963 /* Cancel the vote for XO Core ON
7964 * This is done here for safety purposes in case we re-initialize without turning
7965 * it OFF in any error scenario.
7966 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007967 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07007968 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07007969 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07007970 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7971 {
7972 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
7973 " Power consumed will be high\n");
7974 }
7975 } while (0);
7976
7977 if (0 != ret_status)
7978 {
7979 //Assert Deep sleep signal now to put Libra HW in lowest power state
7980 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7981 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
7982
7983 //Vote off any PMIC voltage supplies
7984 vos_chipPowerDown(NULL, NULL, NULL);
7985#ifdef TIMER_MANAGER
7986 vos_timer_exit();
7987#endif
7988#ifdef MEMORY_DEBUG
7989 vos_mem_exit();
7990#endif
7991
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007992#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007993 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007994#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007995 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
7996 }
7997 else
7998 {
7999 //Send WLAN UP indication to Nlink Service
8000 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8001
8002 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008003 }
8004
8005 EXIT();
8006
8007 return ret_status;
8008}
8009
Jeff Johnson32d95a32012-09-10 13:15:23 -07008010/**---------------------------------------------------------------------------
8011
8012 \brief hdd_module_init() - Init Function
8013
8014 This is the driver entry point (invoked when module is loaded using insmod)
8015
8016 \param - None
8017
8018 \return - 0 for success, non zero for failure
8019
8020 --------------------------------------------------------------------------*/
8021#ifdef MODULE
8022static int __init hdd_module_init ( void)
8023{
8024 return hdd_driver_init();
8025}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008026#else /* #ifdef MODULE */
8027static int __init hdd_module_init ( void)
8028{
8029 /* Driver initialization is delayed to fwpath_changed_handler */
8030 return 0;
8031}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008032#endif /* #ifdef MODULE */
8033
Jeff Johnson295189b2012-06-20 16:38:30 -07008034
8035/**---------------------------------------------------------------------------
8036
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008037 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008038
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008039 This is the driver exit point (invoked when module is unloaded using rmmod
8040 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008041
8042 \param - None
8043
8044 \return - None
8045
8046 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008047static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008048{
8049 hdd_context_t *pHddCtx = NULL;
8050 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008051 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008052
8053 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8054
8055 //Get the global vos context
8056 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8057
8058 if(!pVosContext)
8059 {
8060 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8061 goto done;
8062 }
8063
8064 //Get the HDD context.
8065 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8066
8067 if(!pHddCtx)
8068 {
8069 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8070 }
8071 else
8072 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008073 while(isWDresetInProgress()) {
8074 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8075 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008076 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008077
8078 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8079 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8080 "%s:SSR never completed, fatal error", __func__);
8081 VOS_BUG(0);
8082 }
8083 }
8084
Jeff Johnson295189b2012-06-20 16:38:30 -07008085
8086 pHddCtx->isLoadUnloadInProgress = TRUE;
8087 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8088
8089 //Do all the cleanup before deregistering the driver
8090 hdd_wlan_exit(pHddCtx);
8091 }
8092
Jeff Johnson295189b2012-06-20 16:38:30 -07008093 vos_preClose( &pVosContext );
8094
8095#ifdef TIMER_MANAGER
8096 vos_timer_exit();
8097#endif
8098#ifdef MEMORY_DEBUG
8099 vos_mem_exit();
8100#endif
8101
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308102#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8103 vos_wconn_trace_exit();
8104#endif
8105
Jeff Johnson295189b2012-06-20 16:38:30 -07008106done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008107#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008108 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008109#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008110 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8111}
8112
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008113/**---------------------------------------------------------------------------
8114
8115 \brief hdd_module_exit() - Exit function
8116
8117 This is the driver exit point (invoked when module is unloaded using rmmod)
8118
8119 \param - None
8120
8121 \return - None
8122
8123 --------------------------------------------------------------------------*/
8124static void __exit hdd_module_exit(void)
8125{
8126 hdd_driver_exit();
8127}
8128
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008129#ifdef MODULE
8130static int fwpath_changed_handler(const char *kmessage,
8131 struct kernel_param *kp)
8132{
Jeff Johnson76052702013-04-16 13:55:05 -07008133 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008134}
8135
8136static int con_mode_handler(const char *kmessage,
8137 struct kernel_param *kp)
8138{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008139 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008140}
8141#else /* #ifdef MODULE */
8142/**---------------------------------------------------------------------------
8143
Jeff Johnson76052702013-04-16 13:55:05 -07008144 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008145
Jeff Johnson76052702013-04-16 13:55:05 -07008146 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008147 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008148 - invoked when module parameter fwpath is modified from userspace to signal
8149 initializing the WLAN driver or when con_mode is modified from userspace
8150 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008151
8152 \return - 0 for success, non zero for failure
8153
8154 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008155static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008156{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008157 int ret_status;
8158
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008159 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008160 ret_status = hdd_driver_init();
8161 wlan_hdd_inited = ret_status ? 0 : 1;
8162 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008163 }
8164
8165 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008166
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008167 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008168
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008169 ret_status = hdd_driver_init();
8170 wlan_hdd_inited = ret_status ? 0 : 1;
8171 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008172}
8173
Jeff Johnson295189b2012-06-20 16:38:30 -07008174/**---------------------------------------------------------------------------
8175
Jeff Johnson76052702013-04-16 13:55:05 -07008176 \brief fwpath_changed_handler() - Handler Function
8177
8178 Handle changes to the fwpath parameter
8179
8180 \return - 0 for success, non zero for failure
8181
8182 --------------------------------------------------------------------------*/
8183static int fwpath_changed_handler(const char *kmessage,
8184 struct kernel_param *kp)
8185{
8186 int ret;
8187
8188 ret = param_set_copystring(kmessage, kp);
8189 if (0 == ret)
8190 ret = kickstart_driver();
8191 return ret;
8192}
8193
8194/**---------------------------------------------------------------------------
8195
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008196 \brief con_mode_handler() -
8197
8198 Handler function for module param con_mode when it is changed by userspace
8199 Dynamically linked - do nothing
8200 Statically linked - exit and init driver, as in rmmod and insmod
8201
Jeff Johnson76052702013-04-16 13:55:05 -07008202 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008203
Jeff Johnson76052702013-04-16 13:55:05 -07008204 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008205
8206 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008207static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008208{
Jeff Johnson76052702013-04-16 13:55:05 -07008209 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008210
Jeff Johnson76052702013-04-16 13:55:05 -07008211 ret = param_set_int(kmessage, kp);
8212 if (0 == ret)
8213 ret = kickstart_driver();
8214 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008215}
8216#endif /* #ifdef MODULE */
8217
8218/**---------------------------------------------------------------------------
8219
Jeff Johnson295189b2012-06-20 16:38:30 -07008220 \brief hdd_get_conparam() -
8221
8222 This is the driver exit point (invoked when module is unloaded using rmmod)
8223
8224 \param - None
8225
8226 \return - tVOS_CON_MODE
8227
8228 --------------------------------------------------------------------------*/
8229tVOS_CON_MODE hdd_get_conparam ( void )
8230{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008231#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008232 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008233#else
8234 return (tVOS_CON_MODE)curr_con_mode;
8235#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008236}
8237void hdd_set_conparam ( v_UINT_t newParam )
8238{
8239 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008240#ifndef MODULE
8241 curr_con_mode = con_mode;
8242#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008243}
8244/**---------------------------------------------------------------------------
8245
8246 \brief hdd_softap_sta_deauth() - function
8247
8248 This to take counter measure to handle deauth req from HDD
8249
8250 \param - pAdapter - Pointer to the HDD
8251
8252 \param - enable - boolean value
8253
8254 \return - None
8255
8256 --------------------------------------------------------------------------*/
8257
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008258VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008259{
Jeff Johnson295189b2012-06-20 16:38:30 -07008260 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008261 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008262
8263 ENTER();
8264
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008265 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8266 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008267
8268 //Ignore request to deauth bcmc station
8269 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008270 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008271
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008272 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008273
8274 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008275 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008276}
8277
8278/**---------------------------------------------------------------------------
8279
8280 \brief hdd_softap_sta_disassoc() - function
8281
8282 This to take counter measure to handle deauth req from HDD
8283
8284 \param - pAdapter - Pointer to the HDD
8285
8286 \param - enable - boolean value
8287
8288 \return - None
8289
8290 --------------------------------------------------------------------------*/
8291
8292void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8293{
8294 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8295
8296 ENTER();
8297
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308298 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008299
8300 //Ignore request to disassoc bcmc station
8301 if( pDestMacAddress[0] & 0x1 )
8302 return;
8303
8304 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8305}
8306
8307void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8308{
8309 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8310
8311 ENTER();
8312
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308313 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008314
8315 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8316}
8317
Jeff Johnson295189b2012-06-20 16:38:30 -07008318/**---------------------------------------------------------------------------
8319 *
8320 * \brief hdd_get__concurrency_mode() -
8321 *
8322 *
8323 * \param - None
8324 *
8325 * \return - CONCURRENCY MODE
8326 *
8327 * --------------------------------------------------------------------------*/
8328tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8329{
8330 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8331 hdd_context_t *pHddCtx;
8332
8333 if (NULL != pVosContext)
8334 {
8335 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8336 if (NULL != pHddCtx)
8337 {
8338 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8339 }
8340 }
8341
8342 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008343 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008344 return VOS_STA;
8345}
8346
8347/* Decide whether to allow/not the apps power collapse.
8348 * Allow apps power collapse if we are in connected state.
8349 * if not, allow only if we are in IMPS */
8350v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8351{
8352 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008353 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008354 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008355 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8356 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8357 hdd_adapter_t *pAdapter = NULL;
8358 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008359 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008360
Jeff Johnson295189b2012-06-20 16:38:30 -07008361 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8362 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008363
Yathish9f22e662012-12-10 14:21:35 -08008364 concurrent_state = hdd_get_concurrency_mode();
8365
8366#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8367 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8368 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8369 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8370 return TRUE;
8371#endif
8372
Jeff Johnson295189b2012-06-20 16:38:30 -07008373 /*loop through all adapters. TBD fix for Concurrency */
8374 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8375 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8376 {
8377 pAdapter = pAdapterNode->pAdapter;
8378 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8379 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8380 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008381 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008382 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008383 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008384 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8385 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008386 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008387 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008388 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8389 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008390 return FALSE;
8391 }
8392 }
8393 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8394 pAdapterNode = pNext;
8395 }
8396 return TRUE;
8397}
8398
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008399/* Decides whether to send suspend notification to Riva
8400 * if any adapter is in BMPS; then it is required */
8401v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8402{
8403 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8404 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8405
8406 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8407 {
8408 return TRUE;
8409 }
8410 return FALSE;
8411}
8412
Jeff Johnson295189b2012-06-20 16:38:30 -07008413void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8414{
8415 switch(mode)
8416 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008417 case VOS_STA_MODE:
8418 case VOS_P2P_CLIENT_MODE:
8419 case VOS_P2P_GO_MODE:
8420 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008421 pHddCtx->concurrency_mode |= (1 << mode);
8422 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008423 break;
8424 default:
8425 break;
8426
8427 }
8428 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8429 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8430}
8431
8432
8433void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8434{
8435 switch(mode)
8436 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008437 case VOS_STA_MODE:
8438 case VOS_P2P_CLIENT_MODE:
8439 case VOS_P2P_GO_MODE:
8440 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008441 pHddCtx->no_of_sessions[mode]--;
8442 if (!(pHddCtx->no_of_sessions[mode]))
8443 pHddCtx->concurrency_mode &= (~(1 << mode));
8444 break;
8445 default:
8446 break;
8447 }
8448 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8449 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8450}
8451
Jeff Johnsone7245742012-09-05 17:12:55 -07008452/**---------------------------------------------------------------------------
8453 *
8454 * \brief wlan_hdd_restart_init
8455 *
8456 * This function initalizes restart timer/flag. An internal function.
8457 *
8458 * \param - pHddCtx
8459 *
8460 * \return - None
8461 *
8462 * --------------------------------------------------------------------------*/
8463
8464static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8465{
8466 /* Initialize */
8467 pHddCtx->hdd_restart_retries = 0;
8468 atomic_set(&pHddCtx->isRestartInProgress, 0);
8469 vos_timer_init(&pHddCtx->hdd_restart_timer,
8470 VOS_TIMER_TYPE_SW,
8471 wlan_hdd_restart_timer_cb,
8472 pHddCtx);
8473}
8474/**---------------------------------------------------------------------------
8475 *
8476 * \brief wlan_hdd_restart_deinit
8477 *
8478 * This function cleans up the resources used. An internal function.
8479 *
8480 * \param - pHddCtx
8481 *
8482 * \return - None
8483 *
8484 * --------------------------------------------------------------------------*/
8485
8486static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8487{
8488
8489 VOS_STATUS vos_status;
8490 /* Block any further calls */
8491 atomic_set(&pHddCtx->isRestartInProgress, 1);
8492 /* Cleanup */
8493 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8494 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008495 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008496 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8497 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008498 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008499
8500}
8501
8502/**---------------------------------------------------------------------------
8503 *
8504 * \brief wlan_hdd_framework_restart
8505 *
8506 * This function uses a cfg80211 API to start a framework initiated WLAN
8507 * driver module unload/load.
8508 *
8509 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8510 *
8511 *
8512 * \param - pHddCtx
8513 *
8514 * \return - VOS_STATUS_SUCCESS: Success
8515 * VOS_STATUS_E_EMPTY: Adapter is Empty
8516 * VOS_STATUS_E_NOMEM: No memory
8517
8518 * --------------------------------------------------------------------------*/
8519
8520static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8521{
8522 VOS_STATUS status = VOS_STATUS_SUCCESS;
8523 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008524 int len = (sizeof (struct ieee80211_mgmt));
8525 struct ieee80211_mgmt *mgmt = NULL;
8526
8527 /* Prepare the DEAUTH managment frame with reason code */
8528 mgmt = kzalloc(len, GFP_KERNEL);
8529 if(mgmt == NULL)
8530 {
8531 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8532 "%s: memory allocation failed (%d bytes)", __func__, len);
8533 return VOS_STATUS_E_NOMEM;
8534 }
8535 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008536
8537 /* Iterate over all adapters/devices */
8538 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8539 do
8540 {
8541 if( (status == VOS_STATUS_SUCCESS) &&
8542 pAdapterNode &&
8543 pAdapterNode->pAdapter)
8544 {
8545 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8546 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8547 pAdapterNode->pAdapter->dev->name,
8548 pAdapterNode->pAdapter->device_mode,
8549 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008550 /*
8551 * CFG80211 event to restart the driver
8552 *
8553 * 'cfg80211_send_unprot_deauth' sends a
8554 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8555 * of SME(Linux Kernel) state machine.
8556 *
8557 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8558 * the driver.
8559 *
8560 */
8561
8562 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008563 }
8564 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8565 pAdapterNode = pNext;
8566 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8567
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008568
8569 /* Free the allocated management frame */
8570 kfree(mgmt);
8571
Jeff Johnsone7245742012-09-05 17:12:55 -07008572 /* Retry until we unload or reach max count */
8573 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8574 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8575
8576 return status;
8577
8578}
8579/**---------------------------------------------------------------------------
8580 *
8581 * \brief wlan_hdd_restart_timer_cb
8582 *
8583 * Restart timer callback. An internal function.
8584 *
8585 * \param - User data:
8586 *
8587 * \return - None
8588 *
8589 * --------------------------------------------------------------------------*/
8590
8591void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8592{
8593 hdd_context_t *pHddCtx = usrDataForCallback;
8594 wlan_hdd_framework_restart(pHddCtx);
8595 return;
8596
8597}
8598
8599
8600/**---------------------------------------------------------------------------
8601 *
8602 * \brief wlan_hdd_restart_driver
8603 *
8604 * This function sends an event to supplicant to restart the WLAN driver.
8605 *
8606 * This function is called from vos_wlanRestart.
8607 *
8608 * \param - pHddCtx
8609 *
8610 * \return - VOS_STATUS_SUCCESS: Success
8611 * VOS_STATUS_E_EMPTY: Adapter is Empty
8612 * VOS_STATUS_E_ALREADY: Request already in progress
8613
8614 * --------------------------------------------------------------------------*/
8615VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8616{
8617 VOS_STATUS status = VOS_STATUS_SUCCESS;
8618
8619 /* A tight check to make sure reentrancy */
8620 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8621 {
8622 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8623 "%s: WLAN restart is already in progress", __func__);
8624
8625 return VOS_STATUS_E_ALREADY;
8626 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008627 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008628#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008629 wcnss_reset_intr();
8630#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008631
Jeff Johnsone7245742012-09-05 17:12:55 -07008632 return status;
8633}
8634
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008635/*
8636 * API to find if there is any STA or P2P-Client is connected
8637 */
8638VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8639{
8640 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8641}
Jeff Johnsone7245742012-09-05 17:12:55 -07008642
Jeff Johnson295189b2012-06-20 16:38:30 -07008643//Register the module init/exit functions
8644module_init(hdd_module_init);
8645module_exit(hdd_module_exit);
8646
8647MODULE_LICENSE("Dual BSD/GPL");
8648MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8649MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8650
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008651module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8652 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008653
Jeff Johnson76052702013-04-16 13:55:05 -07008654module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07008655 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);