blob: 2cb0fcc96ed01b3ac5cc341c86185bd12f325b5d [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",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001229 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301230 pTemp += temp_len;
1231 temp_total_len += temp_len;
1232
1233 /*level*/
1234 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1235 pApMetaInfo->ApInfo.rssi);
1236 pTemp += temp_len;
1237 temp_total_len += temp_len;
1238
1239 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001240 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301241 pApMetaInfo->ApInfo.age);
1242 pTemp += temp_len;
1243 temp_total_len += temp_len;
1244
1245 /*dist*/
1246 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1247 pTemp += temp_len;
1248 temp_total_len += temp_len;
1249
1250 /*error*/
1251 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1252 pTemp += temp_len;
1253 temp_total_len += temp_len;
1254
1255 /*end AP marker*/
1256 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1257 pTemp += temp_len;
1258 temp_total_len += temp_len;
1259
1260 /*last AP in batch scan response*/
1261 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1262 {
1263 /*end scan marker*/
1264 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1265 pTemp += temp_len;
1266 temp_total_len += temp_len;
1267
1268 /*end batch scan result marker*/
1269 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1270 pTemp += temp_len;
1271 temp_total_len += temp_len;
1272 }
1273
1274 if (temp_total_len < rem_len)
1275 {
1276 ret = temp_total_len + 1;
1277 strlcpy(pDest, temp, ret);
1278 pAdapter->isTruncated = FALSE;
1279 }
1280 else
1281 {
1282 pAdapter->isTruncated = TRUE;
1283 if (rem_len >= strlen("%%%%"))
1284 {
1285 ret = snprintf(pDest, strlen("%%%%"), "%%%%");
1286 }
1287 {
1288 ret = 0;
1289 }
1290 }
1291
1292 return ret;
1293
1294}/*End of hdd_format_batch_scan_rsp*/
1295
1296/**---------------------------------------------------------------------------
1297
1298 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1299 buffer starting with head of hdd batch scan response queue
1300
1301 \param - pAdapter Pointer to HDD adapter
1302 \param - pDest Pointer to user data buffer
1303 \param - cur_len current offset in user buffer
1304 \param - rem_len remaining no of bytes in user buffer
1305
1306 \return - number of bytes written in user buffer
1307
1308 --------------------------------------------------------------------------*/
1309
1310tANI_U32 hdd_populate_user_batch_scan_rsp
1311(
1312 hdd_adapter_t* pAdapter,
1313 tANI_U8 *pDest,
1314 tANI_U32 cur_len,
1315 tANI_U32 rem_len
1316)
1317{
1318 tHddBatchScanRsp *pHead;
1319 tHddBatchScanRsp *pPrev;
1320 tANI_U32 len;
1321
1322 pAdapter->prev_batch_id = 0;
1323 pAdapter->isTruncated = FALSE;
1324
1325 /*head of hdd batch scan response queue*/
1326 pHead = pAdapter->pBatchScanRsp;
1327 while (pHead)
1328 {
1329 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1330 pAdapter);
1331 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001332 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301333 cur_len += len;
1334 if(TRUE == pAdapter->isTruncated)
1335 {
1336 /*result is truncated return rest of scan rsp in next req*/
1337 cur_len = rem_len;
1338 break;
1339 }
1340 pPrev = pHead;
1341 pHead = pHead->pNext;
1342 pAdapter->pBatchScanRsp = pHead;
1343 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1344 vos_mem_free(pPrev);
1345 }
1346
1347 return cur_len;
1348}/*End of hdd_populate_user_batch_scan_rsp*/
1349
1350/**---------------------------------------------------------------------------
1351
1352 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1353 scan response data from HDD queue to user space
1354 It does following in detail:
1355 a) if HDD has enough data in its queue then it 1st copies data to user
1356 space and then send get batch scan indication message to FW. In this
1357 case it does not wait on any event and batch scan response data will
1358 be populated in HDD response queue in MC thread context after receiving
1359 indication from FW
1360 b) else send get batch scan indication message to FW and wait on an event
1361 which will be set once HDD receives complete batch scan response from
1362 FW and then this function returns batch scan response to user space
1363
1364 \param - pAdapter Pointer to HDD adapter
1365 \param - pPrivData Pointer to priv_data
1366
1367 \return - 0 for success -EFAULT for failure
1368
1369 --------------------------------------------------------------------------*/
1370
1371int hdd_return_batch_scan_rsp_to_user
1372(
1373 hdd_adapter_t* pAdapter,
1374 hdd_priv_data_t *pPrivData,
1375 tANI_U8 *command
1376)
1377{
1378 tANI_U8 *pDest;
1379 tANI_U32 count = 0;
1380 tANI_U32 len = 0;
1381 tANI_U32 cur_len = 0;
1382 tANI_U32 rem_len = 0;
1383 eHalStatus halStatus;
1384 unsigned long rc;
1385 tSirTriggerBatchScanResultInd *pReq;
1386
1387 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1388 pReq->param = 0;/*batch scan client*/
1389 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1390 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1391
1392 cur_len = pPrivData->used_len;
1393 if (pPrivData->total_len > pPrivData->used_len)
1394 {
1395 rem_len = pPrivData->total_len - pPrivData->used_len;
1396 }
1397 else
1398 {
1399 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1400 "%s: Invalid user data buffer total_len %d used_len %d",
1401 __func__, pPrivData->total_len, pPrivData->used_len);
1402 return -EFAULT;
1403 }
1404
1405 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1406 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1407 cur_len, rem_len);
1408 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1409
1410 /*enough scan result available in cache to return to user space or
1411 scan result needs to be fetched 1st from fw and then return*/
1412 if (len < rem_len)
1413 {
1414 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1415 halStatus = sme_TriggerBatchScanResultInd(
1416 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1417 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1418 pAdapter);
1419 if ( eHAL_STATUS_SUCCESS == halStatus )
1420 {
1421 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1422 {
1423 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1424 rc = wait_for_completion_timeout(
1425 &pAdapter->hdd_get_batch_scan_req_var,
1426 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1427 if (0 == rc)
1428 {
1429 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1430 "%s: Timeout waiting to fetch batch scan rsp from fw",
1431 __func__);
1432 return -EFAULT;
1433 }
1434 }
1435
1436 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001437 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301438 pDest += len;
1439 cur_len += len;
1440
1441 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1442 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1443 cur_len, rem_len);
1444 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1445
1446 count = 0;
1447 len = (len - pPrivData->used_len);
1448 pDest = (command + pPrivData->used_len);
1449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1450 "BATCH SCAN RESULT:");
1451 while(count < len)
1452 {
1453 printk("%c", *(pDest + count));
1454 count++;
1455 }
1456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1457 "%s: copy %d data to user buffer", __func__, len);
1458 if (copy_to_user(pPrivData->buf, pDest, len))
1459 {
1460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1461 "%s: failed to copy data to user buffer", __func__);
1462 return -EFAULT;
1463 }
1464 }
1465 else
1466 {
1467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1468 "sme_GetBatchScanScan returned failure halStatus %d",
1469 halStatus);
1470 return -EINVAL;
1471 }
1472 }
1473 else
1474 {
1475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1476 "%s: copy %d data to user buffer", __func__, len);
1477 count = 0;
1478 len = (len - pPrivData->used_len);
1479 pDest = (command + pPrivData->used_len);
1480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1481 "BATCH SCAN RESULT:");
1482 while(count < len)
1483 {
1484 printk("%c", *(pDest + count));
1485 count++;
1486 }
1487 if (copy_to_user(pPrivData->buf, pDest, len))
1488 {
1489 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1490 "%s: failed to copy data to user buffer", __func__);
1491 return -EFAULT;
1492 }
1493 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1494 halStatus = sme_TriggerBatchScanResultInd(
1495 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1496 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1497 pAdapter);
1498 if ( eHAL_STATUS_SUCCESS != halStatus )
1499 {
1500 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1501 "sme_GetBatchScanScan returned failure halStatus %d",
1502 halStatus);
1503 }
1504 }
1505
1506 return 0;
1507} /*End of hdd_return_batch_scan_rsp_to_user*/
1508
1509#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1510
Jeff Johnson295189b2012-06-20 16:38:30 -07001511int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1512{
1513 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1514 hdd_priv_data_t priv_data;
1515 tANI_U8 *command = NULL;
1516 int ret = 0;
1517
1518 if (NULL == pAdapter)
1519 {
1520 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001521 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001522 ret = -ENODEV;
1523 goto exit;
1524 }
1525
Jeff Johnsone7245742012-09-05 17:12:55 -07001526 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001527 {
1528 ret = -EINVAL;
1529 goto exit;
1530 }
1531
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001532 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1533 {
1534 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1535 "%s:LOGP in Progress. Ignore!!!", __func__);
1536 ret = -EBUSY;
1537 goto exit;
1538 }
1539
Jeff Johnson295189b2012-06-20 16:38:30 -07001540 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1541 {
1542 ret = -EFAULT;
1543 goto exit;
1544 }
1545
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001546 if (priv_data.total_len <= 0)
1547 {
1548 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1549 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1550 priv_data.total_len);
1551 ret = -EINVAL;
1552 goto exit;
1553 }
1554
1555 /* Allocate +1 for '\0' */
1556 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001557 if (!command)
1558 {
1559 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001560 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001561 ret = -ENOMEM;
1562 goto exit;
1563 }
1564
1565 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1566 {
1567 ret = -EFAULT;
1568 goto exit;
1569 }
1570
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001571 /* Making sure the command is NUL-terminated */
1572 command[priv_data.total_len] = '\0';
1573
Jeff Johnson295189b2012-06-20 16:38:30 -07001574 if ((SIOCDEVPRIVATE + 1) == cmd)
1575 {
1576 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1577
1578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001579 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001580
1581 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1582 {
1583 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1584 sizeof(tSirMacAddr)))
1585 {
1586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001587 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001588 ret = -EFAULT;
1589 }
1590 }
Amar Singhal0974e402013-02-12 14:27:46 -08001591 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001592 {
Amar Singhal0974e402013-02-12 14:27:46 -08001593 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001594 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001595
Jeff Johnson295189b2012-06-20 16:38:30 -07001596 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001597
1598 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001599 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001600 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001601 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001602 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001603 ret = hdd_setBand_helper(dev, ptr);
1604 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001605 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1606 {
1607 char *country_code;
1608
1609 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001610
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001611 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001612 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301613 hdd_checkandupdate_phymode(pAdapter, country_code);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001614 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1615 (void *)(tSmeChangeCountryCallback)
1616 wlan_hdd_change_country_code_callback,
1617 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1618 if (eHAL_STATUS_SUCCESS == ret)
1619 {
1620 ret = wait_for_completion_interruptible_timeout(
1621 &pAdapter->change_country_code,
1622 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1623 if (0 >= ret)
1624 {
1625 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1626 __func__);
1627 }
1628 }
1629 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001630 {
1631 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001632 "%s: SME Change Country code fail ret=%d", __func__, ret);
1633 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001634 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001635
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001636 }
1637 /*
1638 command should be a string having format
1639 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1640 */
Amar Singhal0974e402013-02-12 14:27:46 -08001641 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001642 {
Amar Singhal0974e402013-02-12 14:27:46 -08001643 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001644
1645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001646 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001647
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001648 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001649 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001650 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1651 {
1652 int suspend = 0;
1653 tANI_U8 *ptr = (tANI_U8*)command + 15;
1654
1655 suspend = *ptr - '0';
1656 hdd_set_wlan_suspend_mode(suspend);
1657 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001658#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1659 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1660 {
1661 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001662 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001663 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1664 eHalStatus status = eHAL_STATUS_SUCCESS;
1665
1666 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1667 value = value + 15;
1668
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001669 /* Convert the value from ascii to integer */
1670 ret = kstrtos8(value, 10, &rssi);
1671 if (ret < 0)
1672 {
1673 /* If the input value is greater than max value of datatype, then also
1674 kstrtou8 fails */
1675 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1676 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001677 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001678 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1679 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1680 ret = -EINVAL;
1681 goto exit;
1682 }
1683
Srinivas Girigowdade697412013-02-14 16:31:48 -08001684 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001685
Srinivas Girigowdade697412013-02-14 16:31:48 -08001686 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1687 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1688 {
1689 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1690 "Neighbor lookup threshold value %d is out of range"
1691 " (Min: %d Max: %d)", lookUpThreshold,
1692 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1693 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1694 ret = -EINVAL;
1695 goto exit;
1696 }
1697
1698 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1699 "%s: Received Command to Set Roam trigger"
1700 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1701
1702 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1703 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1704 if (eHAL_STATUS_SUCCESS != status)
1705 {
1706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1707 "%s: Failed to set roam trigger, try again", __func__);
1708 ret = -EPERM;
1709 goto exit;
1710 }
1711
1712 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1713 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1714 }
1715 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1716 {
1717 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1718 int rssi = (-1) * lookUpThreshold;
1719 char extra[32];
1720 tANI_U8 len = 0;
1721
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001722 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001723 if (copy_to_user(priv_data.buf, &extra, len + 1))
1724 {
1725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1726 "%s: failed to copy data to user buffer", __func__);
1727 ret = -EFAULT;
1728 goto exit;
1729 }
1730 }
1731 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1732 {
1733 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001734 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001735 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001736
Srinivas Girigowdade697412013-02-14 16:31:48 -08001737 /* input refresh period is in terms of seconds */
1738 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1739 value = value + 18;
1740 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001741 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001742 if (ret < 0)
1743 {
1744 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001745 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001747 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001748 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001749 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1750 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001751 ret = -EINVAL;
1752 goto exit;
1753 }
1754
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001755 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1756 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001757 {
1758 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001759 "Roam scan period value %d is out of range"
1760 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001761 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1762 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001763 ret = -EINVAL;
1764 goto exit;
1765 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001766 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001767
1768 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1769 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001770 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001771
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001772 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1773 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001774 }
1775 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1776 {
1777 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1778 char extra[32];
1779 tANI_U8 len = 0;
1780
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001781 len = scnprintf(extra, sizeof(extra), "%s %d",
1782 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001783 /* Returned value is in units of seconds */
1784 if (copy_to_user(priv_data.buf, &extra, len + 1))
1785 {
1786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1787 "%s: failed to copy data to user buffer", __func__);
1788 ret = -EFAULT;
1789 goto exit;
1790 }
1791 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001792 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1793 {
1794 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001795 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001796 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001797
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001798 /* input refresh period is in terms of seconds */
1799 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1800 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001801
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001802 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001803 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001804 if (ret < 0)
1805 {
1806 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001807 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001809 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001810 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001811 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1812 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1813 ret = -EINVAL;
1814 goto exit;
1815 }
1816
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001817 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1818 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1819 {
1820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1821 "Neighbor scan results refresh period value %d is out of range"
1822 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1823 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1824 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1825 ret = -EINVAL;
1826 goto exit;
1827 }
1828 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1829
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1831 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001832 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001833
1834 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1835 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1836 }
1837 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1838 {
1839 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1840 char extra[32];
1841 tANI_U8 len = 0;
1842
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001843 len = scnprintf(extra, sizeof(extra), "%s %d",
1844 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001845 /* Returned value is in units of seconds */
1846 if (copy_to_user(priv_data.buf, &extra, len + 1))
1847 {
1848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1849 "%s: failed to copy data to user buffer", __func__);
1850 ret = -EFAULT;
1851 goto exit;
1852 }
1853 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001854#ifdef FEATURE_WLAN_LFR
1855 /* SETROAMMODE */
1856 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1857 {
1858 tANI_U8 *value = command;
1859 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1860
1861 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1862 value = value + SIZE_OF_SETROAMMODE + 1;
1863
1864 /* Convert the value from ascii to integer */
1865 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1866 if (ret < 0)
1867 {
1868 /* If the input value is greater than max value of datatype, then also
1869 kstrtou8 fails */
1870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1871 "%s: kstrtou8 failed range [%d - %d]", __func__,
1872 CFG_LFR_FEATURE_ENABLED_MIN,
1873 CFG_LFR_FEATURE_ENABLED_MAX);
1874 ret = -EINVAL;
1875 goto exit;
1876 }
1877 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1878 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1879 {
1880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1881 "Roam Mode value %d is out of range"
1882 " (Min: %d Max: %d)", roamMode,
1883 CFG_LFR_FEATURE_ENABLED_MIN,
1884 CFG_LFR_FEATURE_ENABLED_MAX);
1885 ret = -EINVAL;
1886 goto exit;
1887 }
1888
1889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1890 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
1891 /*
1892 * Note that
1893 * SETROAMMODE 0 is to enable LFR while
1894 * SETROAMMODE 1 is to disable LFR, but
1895 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
1896 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
1897 */
1898 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1899 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
1900 else
1901 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
1902
1903 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
1904 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
1905 }
1906 /* GETROAMMODE */
1907 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
1908 {
1909 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
1910 char extra[32];
1911 tANI_U8 len = 0;
1912
1913 /*
1914 * roamMode value shall be inverted because the sementics is different.
1915 */
1916 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
1917 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
1918 else
1919 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
1920
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001921 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001922 if (copy_to_user(priv_data.buf, &extra, len + 1))
1923 {
1924 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1925 "%s: failed to copy data to user buffer", __func__);
1926 ret = -EFAULT;
1927 goto exit;
1928 }
1929 }
1930#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08001931#endif
1932#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1933 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
1934 {
1935 tANI_U8 *value = command;
1936 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
1937
1938 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
1939 value = value + 13;
1940 /* Convert the value from ascii to integer */
1941 ret = kstrtou8(value, 10, &roamRssiDiff);
1942 if (ret < 0)
1943 {
1944 /* If the input value is greater than max value of datatype, then also
1945 kstrtou8 fails */
1946 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1947 "%s: kstrtou8 failed range [%d - %d]", __func__,
1948 CFG_ROAM_RSSI_DIFF_MIN,
1949 CFG_ROAM_RSSI_DIFF_MAX);
1950 ret = -EINVAL;
1951 goto exit;
1952 }
1953
1954 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
1955 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
1956 {
1957 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1958 "Roam rssi diff value %d is out of range"
1959 " (Min: %d Max: %d)", roamRssiDiff,
1960 CFG_ROAM_RSSI_DIFF_MIN,
1961 CFG_ROAM_RSSI_DIFF_MAX);
1962 ret = -EINVAL;
1963 goto exit;
1964 }
1965
1966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1967 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
1968
1969 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
1970 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
1971 }
1972 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
1973 {
1974 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
1975 char extra[32];
1976 tANI_U8 len = 0;
1977
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001978 len = scnprintf(extra, sizeof(extra), "%s %d",
1979 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001980 if (copy_to_user(priv_data.buf, &extra, len + 1))
1981 {
1982 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1983 "%s: failed to copy data to user buffer", __func__);
1984 ret = -EFAULT;
1985 goto exit;
1986 }
1987 }
1988#endif
1989#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
1990 else if (strncmp(command, "GETBAND", 7) == 0)
1991 {
1992 int band = -1;
1993 char extra[32];
1994 tANI_U8 len = 0;
1995 hdd_getBand_helper(pHddCtx, &band);
1996
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001997 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001998 if (copy_to_user(priv_data.buf, &extra, len + 1))
1999 {
2000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2001 "%s: failed to copy data to user buffer", __func__);
2002 ret = -EFAULT;
2003 goto exit;
2004 }
2005 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002006 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2007 {
2008 tANI_U8 *value = command;
2009 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2010 tANI_U8 numChannels = 0;
2011 eHalStatus status = eHAL_STATUS_SUCCESS;
2012
2013 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2014 if (eHAL_STATUS_SUCCESS != status)
2015 {
2016 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2017 "%s: Failed to parse channel list information", __func__);
2018 ret = -EINVAL;
2019 goto exit;
2020 }
2021
2022 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2023 {
2024 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2025 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2026 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2027 ret = -EINVAL;
2028 goto exit;
2029 }
2030 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2031 numChannels);
2032 if (eHAL_STATUS_SUCCESS != status)
2033 {
2034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2035 "%s: Failed to update channel list information", __func__);
2036 ret = -EINVAL;
2037 goto exit;
2038 }
2039 }
2040 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2041 {
2042 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2043 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002044 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002045 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002046 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002047
2048 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2049 ChannelList, &numChannels ))
2050 {
2051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2052 "%s: failed to get roam scan channel list", __func__);
2053 ret = -EFAULT;
2054 goto exit;
2055 }
2056 /* output channel list is of the format
2057 [Number of roam scan channels][Channel1][Channel2]... */
2058 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002059 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002060 for (j = 0; (j < numChannels); j++)
2061 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002062 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2063 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002064 }
2065
2066 if (copy_to_user(priv_data.buf, &extra, len + 1))
2067 {
2068 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2069 "%s: failed to copy data to user buffer", __func__);
2070 ret = -EFAULT;
2071 goto exit;
2072 }
2073 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002074 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2075 {
2076 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2077 char extra[32];
2078 tANI_U8 len = 0;
2079
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002080 /* Check if the features OKC/CCX/11R are supported simultaneously,
2081 then this operation is not permitted (return FAILURE) */
2082 if (ccxMode &&
2083 hdd_is_okc_mode_enabled(pHddCtx) &&
2084 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2085 {
2086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2087 "%s: OKC/CCX/11R are supported simultaneously"
2088 " hence this operation is not permitted!", __func__);
2089 ret = -EPERM;
2090 goto exit;
2091 }
2092
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002093 len = scnprintf(extra, sizeof(extra), "%s %d",
2094 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002095 if (copy_to_user(priv_data.buf, &extra, len + 1))
2096 {
2097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2098 "%s: failed to copy data to user buffer", __func__);
2099 ret = -EFAULT;
2100 goto exit;
2101 }
2102 }
2103 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2104 {
2105 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2106 char extra[32];
2107 tANI_U8 len = 0;
2108
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002109 /* Check if the features OKC/CCX/11R are supported simultaneously,
2110 then this operation is not permitted (return FAILURE) */
2111 if (okcMode &&
2112 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2113 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2114 {
2115 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2116 "%s: OKC/CCX/11R are supported simultaneously"
2117 " hence this operation is not permitted!", __func__);
2118 ret = -EPERM;
2119 goto exit;
2120 }
2121
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002122 len = scnprintf(extra, sizeof(extra), "%s %d",
2123 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002124 if (copy_to_user(priv_data.buf, &extra, len + 1))
2125 {
2126 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2127 "%s: failed to copy data to user buffer", __func__);
2128 ret = -EFAULT;
2129 goto exit;
2130 }
2131 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002132 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002133 {
2134 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2135 char extra[32];
2136 tANI_U8 len = 0;
2137
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002138 len = scnprintf(extra, sizeof(extra), "%s %d",
2139 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002140 if (copy_to_user(priv_data.buf, &extra, len + 1))
2141 {
2142 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2143 "%s: failed to copy data to user buffer", __func__);
2144 ret = -EFAULT;
2145 goto exit;
2146 }
2147 }
2148 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2149 {
2150 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2151 char extra[32];
2152 tANI_U8 len = 0;
2153
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002154 len = scnprintf(extra, sizeof(extra), "%s %d",
2155 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002156 if (copy_to_user(priv_data.buf, &extra, len + 1))
2157 {
2158 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2159 "%s: failed to copy data to user buffer", __func__);
2160 ret = -EFAULT;
2161 goto exit;
2162 }
2163 }
2164 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2165 {
2166 tANI_U8 *value = command;
2167 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2168
2169 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2170 value = value + 26;
2171 /* Convert the value from ascii to integer */
2172 ret = kstrtou8(value, 10, &minTime);
2173 if (ret < 0)
2174 {
2175 /* If the input value is greater than max value of datatype, then also
2176 kstrtou8 fails */
2177 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2178 "%s: kstrtou8 failed range [%d - %d]", __func__,
2179 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2180 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2181 ret = -EINVAL;
2182 goto exit;
2183 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002184 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2185 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2186 {
2187 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2188 "scan min channel time value %d is out of range"
2189 " (Min: %d Max: %d)", minTime,
2190 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2191 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2192 ret = -EINVAL;
2193 goto exit;
2194 }
2195
2196 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2197 "%s: Received Command to change channel min time = %d", __func__, minTime);
2198
2199 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2200 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2201 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002202 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2203 {
2204 tANI_U8 *value = command;
2205 tANI_U8 channel = 0;
2206 tANI_U8 dwellTime = 0;
2207 tANI_U8 bufLen = 0;
2208 tANI_U8 *buf = NULL;
2209 tSirMacAddr targetApBssid;
2210 eHalStatus status = eHAL_STATUS_SUCCESS;
2211 struct ieee80211_channel chan;
2212 tANI_U8 finalLen = 0;
2213 tANI_U8 *finalBuf = NULL;
2214 tANI_U8 temp = 0;
2215 u64 cookie;
2216 hdd_station_ctx_t *pHddStaCtx = NULL;
2217 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2218
2219 /* if not associated, no need to send action frame */
2220 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2221 {
2222 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2223 ret = -EINVAL;
2224 goto exit;
2225 }
2226
2227 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2228 &dwellTime, &buf, &bufLen);
2229 if (eHAL_STATUS_SUCCESS != status)
2230 {
2231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2232 "%s: Failed to parse send action frame data", __func__);
2233 ret = -EINVAL;
2234 goto exit;
2235 }
2236
2237 /* if the target bssid is different from currently associated AP,
2238 then no need to send action frame */
2239 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2240 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2241 {
2242 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2243 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002244 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002245 goto exit;
2246 }
2247
2248 /* if the channel number is different from operating channel then
2249 no need to send action frame */
2250 if (channel != pHddStaCtx->conn_info.operationChannel)
2251 {
2252 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2253 "%s: channel(%d) is different from operating channel(%d)",
2254 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2255 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002256 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002257 goto exit;
2258 }
2259 chan.center_freq = sme_ChnToFreq(channel);
2260
2261 finalLen = bufLen + 24;
2262 finalBuf = vos_mem_malloc(finalLen);
2263 if (NULL == finalBuf)
2264 {
2265 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2266 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002267 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002268 goto exit;
2269 }
2270 vos_mem_zero(finalBuf, finalLen);
2271
2272 /* Fill subtype */
2273 temp = SIR_MAC_MGMT_ACTION << 4;
2274 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2275
2276 /* Fill type */
2277 temp = SIR_MAC_MGMT_FRAME;
2278 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2279
2280 /* Fill destination address (bssid of the AP) */
2281 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2282
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002283 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002284 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2285
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002286 /* Fill BSSID (AP mac address) */
2287 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002288
2289 /* Fill received buffer from 24th address */
2290 vos_mem_copy(finalBuf + 24, buf, bufLen);
2291
Jeff Johnson11c33152013-04-16 17:52:40 -07002292 /* done with the parsed buffer */
2293 vos_mem_free(buf);
2294
Yue Maf49ba872013-08-19 12:04:25 -07002295 wlan_hdd_action( NULL,
2296#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2297 &(pAdapter->wdev),
2298#else
2299 dev,
2300#endif
2301 &chan, 0,
2302#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2303 NL80211_CHAN_HT20, 1,
2304#endif
2305 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002306 1, &cookie );
2307 vos_mem_free(finalBuf);
2308 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002309 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2310 {
2311 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2312 char extra[32];
2313 tANI_U8 len = 0;
2314
2315 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002316 len = scnprintf(extra, sizeof(extra), "%s %d",
2317 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002318 if (copy_to_user(priv_data.buf, &extra, len + 1))
2319 {
2320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2321 "%s: failed to copy data to user buffer", __func__);
2322 ret = -EFAULT;
2323 goto exit;
2324 }
2325 }
2326 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2327 {
2328 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002329 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002330 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002331
2332 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2333 value = value + 19;
2334 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002335 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002336 if (ret < 0)
2337 {
2338 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002339 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002341 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002342 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2343 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2344 ret = -EINVAL;
2345 goto exit;
2346 }
2347
2348 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2349 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2350 {
2351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2352 "lfr mode value %d is out of range"
2353 " (Min: %d Max: %d)", maxTime,
2354 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2355 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2356 ret = -EINVAL;
2357 goto exit;
2358 }
2359
2360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2361 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2362
2363 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002364
2365 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2366 * where RFS is the RF Switching time. It is twice RFS to consider the
2367 * time to go off channel and return to the home channel. */
2368 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2369 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2370 {
2371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002372 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)"
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002373 " Hence enforcing home away time to disable (0)",
2374 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2375 homeAwayTime = 0;
2376 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2377 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2378 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002379 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2380 }
2381 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2382 {
2383 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2384 char extra[32];
2385 tANI_U8 len = 0;
2386
2387 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002388 len = scnprintf(extra, sizeof(extra), "%s %d",
2389 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002390 if (copy_to_user(priv_data.buf, &extra, len + 1))
2391 {
2392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2393 "%s: failed to copy data to user buffer", __func__);
2394 ret = -EFAULT;
2395 goto exit;
2396 }
2397 }
2398 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2399 {
2400 tANI_U8 *value = command;
2401 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2402
2403 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2404 value = value + 16;
2405 /* Convert the value from ascii to integer */
2406 ret = kstrtou16(value, 10, &val);
2407 if (ret < 0)
2408 {
2409 /* If the input value is greater than max value of datatype, then also
2410 kstrtou16 fails */
2411 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2412 "%s: kstrtou16 failed range [%d - %d]", __func__,
2413 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2414 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2415 ret = -EINVAL;
2416 goto exit;
2417 }
2418
2419 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2420 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2421 {
2422 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2423 "scan home time value %d is out of range"
2424 " (Min: %d Max: %d)", val,
2425 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2426 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2427 ret = -EINVAL;
2428 goto exit;
2429 }
2430
2431 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2432 "%s: Received Command to change scan home time = %d", __func__, val);
2433
2434 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2435 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2436 }
2437 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2438 {
2439 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2440 char extra[32];
2441 tANI_U8 len = 0;
2442
2443 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002444 len = scnprintf(extra, sizeof(extra), "%s %d",
2445 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002446 if (copy_to_user(priv_data.buf, &extra, len + 1))
2447 {
2448 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2449 "%s: failed to copy data to user buffer", __func__);
2450 ret = -EFAULT;
2451 goto exit;
2452 }
2453 }
2454 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2455 {
2456 tANI_U8 *value = command;
2457 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2458
2459 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2460 value = value + 17;
2461 /* Convert the value from ascii to integer */
2462 ret = kstrtou8(value, 10, &val);
2463 if (ret < 0)
2464 {
2465 /* If the input value is greater than max value of datatype, then also
2466 kstrtou8 fails */
2467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2468 "%s: kstrtou8 failed range [%d - %d]", __func__,
2469 CFG_ROAM_INTRA_BAND_MIN,
2470 CFG_ROAM_INTRA_BAND_MAX);
2471 ret = -EINVAL;
2472 goto exit;
2473 }
2474
2475 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2476 (val > CFG_ROAM_INTRA_BAND_MAX))
2477 {
2478 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2479 "intra band mode value %d is out of range"
2480 " (Min: %d Max: %d)", val,
2481 CFG_ROAM_INTRA_BAND_MIN,
2482 CFG_ROAM_INTRA_BAND_MAX);
2483 ret = -EINVAL;
2484 goto exit;
2485 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002486 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2487 "%s: Received Command to change intra band = %d", __func__, val);
2488
2489 pHddCtx->cfg_ini->nRoamIntraBand = val;
2490 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2491 }
2492 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2493 {
2494 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2495 char extra[32];
2496 tANI_U8 len = 0;
2497
2498 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002499 len = scnprintf(extra, sizeof(extra), "%s %d",
2500 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002501 if (copy_to_user(priv_data.buf, &extra, len + 1))
2502 {
2503 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2504 "%s: failed to copy data to user buffer", __func__);
2505 ret = -EFAULT;
2506 goto exit;
2507 }
2508 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002509 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2510 {
2511 tANI_U8 *value = command;
2512 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2513
2514 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2515 value = value + 15;
2516 /* Convert the value from ascii to integer */
2517 ret = kstrtou8(value, 10, &nProbes);
2518 if (ret < 0)
2519 {
2520 /* If the input value is greater than max value of datatype, then also
2521 kstrtou8 fails */
2522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2523 "%s: kstrtou8 failed range [%d - %d]", __func__,
2524 CFG_ROAM_SCAN_N_PROBES_MIN,
2525 CFG_ROAM_SCAN_N_PROBES_MAX);
2526 ret = -EINVAL;
2527 goto exit;
2528 }
2529
2530 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2531 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2532 {
2533 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2534 "NProbes value %d is out of range"
2535 " (Min: %d Max: %d)", nProbes,
2536 CFG_ROAM_SCAN_N_PROBES_MIN,
2537 CFG_ROAM_SCAN_N_PROBES_MAX);
2538 ret = -EINVAL;
2539 goto exit;
2540 }
2541
2542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2543 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2544
2545 pHddCtx->cfg_ini->nProbes = nProbes;
2546 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2547 }
2548 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2549 {
2550 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2551 char extra[32];
2552 tANI_U8 len = 0;
2553
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002554 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002555 if (copy_to_user(priv_data.buf, &extra, len + 1))
2556 {
2557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2558 "%s: failed to copy data to user buffer", __func__);
2559 ret = -EFAULT;
2560 goto exit;
2561 }
2562 }
2563 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2564 {
2565 tANI_U8 *value = command;
2566 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002567 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002568
2569 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2570 /* input value is in units of msec */
2571 value = value + 20;
2572 /* Convert the value from ascii to integer */
2573 ret = kstrtou16(value, 10, &homeAwayTime);
2574 if (ret < 0)
2575 {
2576 /* If the input value is greater than max value of datatype, then also
2577 kstrtou8 fails */
2578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2579 "%s: kstrtou8 failed range [%d - %d]", __func__,
2580 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2581 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2582 ret = -EINVAL;
2583 goto exit;
2584 }
2585
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002586 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2587 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2588 {
2589 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2590 "homeAwayTime value %d is out of range"
2591 " (Min: %d Max: %d)", homeAwayTime,
2592 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2593 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2594 ret = -EINVAL;
2595 goto exit;
2596 }
2597
2598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2599 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2600
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002601 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2602 * where RFS is the RF Switching time. It is twice RFS to consider the
2603 * time to go off channel and return to the home channel. */
2604 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2605 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2606 {
2607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002608 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)"
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002609 " Hence enforcing home away time to disable (0)",
2610 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2611 homeAwayTime = 0;
2612 }
2613
2614 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2615 {
2616 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2617 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2618 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002619 }
2620 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2621 {
2622 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2623 char extra[32];
2624 tANI_U8 len = 0;
2625
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002626 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002627 if (copy_to_user(priv_data.buf, &extra, len + 1))
2628 {
2629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2630 "%s: failed to copy data to user buffer", __func__);
2631 ret = -EFAULT;
2632 goto exit;
2633 }
2634 }
2635 else if (strncmp(command, "REASSOC", 7) == 0)
2636 {
2637 tANI_U8 *value = command;
2638 tANI_U8 channel = 0;
2639 tSirMacAddr targetApBssid;
2640 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002641#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2642 tCsrHandoffRequest handoffInfo;
2643#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002644 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002645 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2646
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002647 /* if not associated, no need to proceed with reassoc */
2648 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2649 {
2650 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2651 ret = -EINVAL;
2652 goto exit;
2653 }
2654
2655 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2656 if (eHAL_STATUS_SUCCESS != status)
2657 {
2658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2659 "%s: Failed to parse reassoc command data", __func__);
2660 ret = -EINVAL;
2661 goto exit;
2662 }
2663
2664 /* if the target bssid is same as currently associated AP,
2665 then no need to proceed with reassoc */
2666 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2667 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2668 {
2669 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2670 ret = -EINVAL;
2671 goto exit;
2672 }
2673
2674 /* Check channel number is a valid channel number */
2675 if(VOS_STATUS_SUCCESS !=
2676 wlan_hdd_validate_operation_channel(pAdapter, channel))
2677 {
2678 hddLog(VOS_TRACE_LEVEL_ERROR,
2679 "%s: Invalid Channel [%d] \n", __func__, channel);
2680 return -EINVAL;
2681 }
2682
2683 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002684#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2685 handoffInfo.channel = channel;
2686 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2687 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2688#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002689 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002690 else if (strncmp(command, "SETWESMODE", 10) == 0)
2691 {
2692 tANI_U8 *value = command;
2693 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2694
2695 /* Move pointer to ahead of SETWESMODE<delimiter> */
2696 value = value + 11;
2697 /* Convert the value from ascii to integer */
2698 ret = kstrtou8(value, 10, &wesMode);
2699 if (ret < 0)
2700 {
2701 /* If the input value is greater than max value of datatype, then also
2702 kstrtou8 fails */
2703 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2704 "%s: kstrtou8 failed range [%d - %d]", __func__,
2705 CFG_ENABLE_WES_MODE_NAME_MIN,
2706 CFG_ENABLE_WES_MODE_NAME_MAX);
2707 ret = -EINVAL;
2708 goto exit;
2709 }
2710
2711 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2712 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2713 {
2714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2715 "WES Mode value %d is out of range"
2716 " (Min: %d Max: %d)", wesMode,
2717 CFG_ENABLE_WES_MODE_NAME_MIN,
2718 CFG_ENABLE_WES_MODE_NAME_MAX);
2719 ret = -EINVAL;
2720 goto exit;
2721 }
2722 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2723 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2724
2725 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2726 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2727 }
2728 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2729 {
2730 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2731 char extra[32];
2732 tANI_U8 len = 0;
2733
2734 len = snprintf(extra, sizeof(extra), "%s %d", command, wesMode);
2735 if (copy_to_user(priv_data.buf, &extra, len + 1))
2736 {
2737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2738 "%s: failed to copy data to user buffer", __func__);
2739 ret = -EFAULT;
2740 goto exit;
2741 }
2742 }
2743#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002744#ifdef FEATURE_WLAN_LFR
2745 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2746 {
2747 tANI_U8 *value = command;
2748 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2749
2750 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2751 value = value + 12;
2752 /* Convert the value from ascii to integer */
2753 ret = kstrtou8(value, 10, &lfrMode);
2754 if (ret < 0)
2755 {
2756 /* If the input value is greater than max value of datatype, then also
2757 kstrtou8 fails */
2758 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2759 "%s: kstrtou8 failed range [%d - %d]", __func__,
2760 CFG_LFR_FEATURE_ENABLED_MIN,
2761 CFG_LFR_FEATURE_ENABLED_MAX);
2762 ret = -EINVAL;
2763 goto exit;
2764 }
2765
2766 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2767 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2768 {
2769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2770 "lfr mode value %d is out of range"
2771 " (Min: %d Max: %d)", lfrMode,
2772 CFG_LFR_FEATURE_ENABLED_MIN,
2773 CFG_LFR_FEATURE_ENABLED_MAX);
2774 ret = -EINVAL;
2775 goto exit;
2776 }
2777
2778 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2779 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2780
2781 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2782 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2783 }
2784#endif
2785#ifdef WLAN_FEATURE_VOWIFI_11R
2786 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2787 {
2788 tANI_U8 *value = command;
2789 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2790
2791 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2792 value = value + 18;
2793 /* Convert the value from ascii to integer */
2794 ret = kstrtou8(value, 10, &ft);
2795 if (ret < 0)
2796 {
2797 /* If the input value is greater than max value of datatype, then also
2798 kstrtou8 fails */
2799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2800 "%s: kstrtou8 failed range [%d - %d]", __func__,
2801 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2802 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2803 ret = -EINVAL;
2804 goto exit;
2805 }
2806
2807 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2808 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2809 {
2810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2811 "ft mode value %d is out of range"
2812 " (Min: %d Max: %d)", ft,
2813 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2814 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2815 ret = -EINVAL;
2816 goto exit;
2817 }
2818
2819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2820 "%s: Received Command to change ft mode = %d", __func__, ft);
2821
2822 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2823 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2824 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302825
2826 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2827 {
2828 tANI_U8 *value = command;
2829 tSirMacAddr targetApBssid;
2830 tANI_U8 trigger = 0;
2831 eHalStatus status = eHAL_STATUS_SUCCESS;
2832 hdd_station_ctx_t *pHddStaCtx = NULL;
2833 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2834
2835 /* if not associated, no need to proceed with reassoc */
2836 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2837 {
2838 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2839 ret = -EINVAL;
2840 goto exit;
2841 }
2842
2843 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2844 if (eHAL_STATUS_SUCCESS != status)
2845 {
2846 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2847 "%s: Failed to parse reassoc command data", __func__);
2848 ret = -EINVAL;
2849 goto exit;
2850 }
2851
2852 /* if the target bssid is same as currently associated AP,
2853 then no need to proceed with reassoc */
2854 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2855 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2856 {
2857 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2858 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2859 __func__);
2860 ret = -EINVAL;
2861 goto exit;
2862 }
2863
2864 /* Proceed with scan/roam */
2865 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2866 &targetApBssid[0],
2867 (tSmeFastRoamTrigger)(trigger));
2868 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002869#endif
2870#ifdef FEATURE_WLAN_CCX
2871 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2872 {
2873 tANI_U8 *value = command;
2874 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2875
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002876 /* Check if the features OKC/CCX/11R are supported simultaneously,
2877 then this operation is not permitted (return FAILURE) */
2878 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2879 hdd_is_okc_mode_enabled(pHddCtx) &&
2880 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2881 {
2882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2883 "%s: OKC/CCX/11R are supported simultaneously"
2884 " hence this operation is not permitted!", __func__);
2885 ret = -EPERM;
2886 goto exit;
2887 }
2888
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002889 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2890 value = value + 11;
2891 /* Convert the value from ascii to integer */
2892 ret = kstrtou8(value, 10, &ccxMode);
2893 if (ret < 0)
2894 {
2895 /* If the input value is greater than max value of datatype, then also
2896 kstrtou8 fails */
2897 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2898 "%s: kstrtou8 failed range [%d - %d]", __func__,
2899 CFG_CCX_FEATURE_ENABLED_MIN,
2900 CFG_CCX_FEATURE_ENABLED_MAX);
2901 ret = -EINVAL;
2902 goto exit;
2903 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002904 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2905 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2906 {
2907 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2908 "Ccx mode value %d is out of range"
2909 " (Min: %d Max: %d)", ccxMode,
2910 CFG_CCX_FEATURE_ENABLED_MIN,
2911 CFG_CCX_FEATURE_ENABLED_MAX);
2912 ret = -EINVAL;
2913 goto exit;
2914 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2916 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
2917
2918 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
2919 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
2920 }
2921#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002922 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
2923 {
2924 tANI_U8 *value = command;
2925 tANI_BOOLEAN roamScanControl = 0;
2926
2927 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
2928 value = value + 19;
2929 /* Convert the value from ascii to integer */
2930 ret = kstrtou8(value, 10, &roamScanControl);
2931 if (ret < 0)
2932 {
2933 /* If the input value is greater than max value of datatype, then also
2934 kstrtou8 fails */
2935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2936 "%s: kstrtou8 failed ", __func__);
2937 ret = -EINVAL;
2938 goto exit;
2939 }
2940
2941 if (0 != roamScanControl)
2942 {
2943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2944 "roam scan control invalid value = %d",
2945 roamScanControl);
2946 ret = -EINVAL;
2947 goto exit;
2948 }
2949 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2950 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
2951
2952 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
2953 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002954#ifdef FEATURE_WLAN_OKC
2955 else if (strncmp(command, "SETOKCMODE", 10) == 0)
2956 {
2957 tANI_U8 *value = command;
2958 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
2959
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002960 /* Check if the features OKC/CCX/11R are supported simultaneously,
2961 then this operation is not permitted (return FAILURE) */
2962 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2963 hdd_is_okc_mode_enabled(pHddCtx) &&
2964 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2965 {
2966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2967 "%s: OKC/CCX/11R are supported simultaneously"
2968 " hence this operation is not permitted!", __func__);
2969 ret = -EPERM;
2970 goto exit;
2971 }
2972
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002973 /* Move pointer to ahead of SETOKCMODE<delimiter> */
2974 value = value + 11;
2975 /* Convert the value from ascii to integer */
2976 ret = kstrtou8(value, 10, &okcMode);
2977 if (ret < 0)
2978 {
2979 /* If the input value is greater than max value of datatype, then also
2980 kstrtou8 fails */
2981 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2982 "%s: kstrtou8 failed range [%d - %d]", __func__,
2983 CFG_OKC_FEATURE_ENABLED_MIN,
2984 CFG_OKC_FEATURE_ENABLED_MAX);
2985 ret = -EINVAL;
2986 goto exit;
2987 }
2988
2989 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
2990 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
2991 {
2992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2993 "Okc mode value %d is out of range"
2994 " (Min: %d Max: %d)", okcMode,
2995 CFG_OKC_FEATURE_ENABLED_MIN,
2996 CFG_OKC_FEATURE_ENABLED_MAX);
2997 ret = -EINVAL;
2998 goto exit;
2999 }
3000
3001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3002 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3003
3004 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3005 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003006#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003007 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3008 {
3009 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3010 char extra[32];
3011 tANI_U8 len = 0;
3012
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003013 len = scnprintf(extra, sizeof(extra), "%s %d",
3014 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003015 if (copy_to_user(priv_data.buf, &extra, len + 1))
3016 {
3017 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3018 "%s: failed to copy data to user buffer", __func__);
3019 ret = -EFAULT;
3020 goto exit;
3021 }
3022 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303023#ifdef WLAN_FEATURE_PACKET_FILTERING
3024 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3025 {
3026 tANI_U8 filterType = 0;
3027 tANI_U8 *value = command;
3028
3029 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3030 value = value + 22;
3031
3032 /* Convert the value from ascii to integer */
3033 ret = kstrtou8(value, 10, &filterType);
3034 if (ret < 0)
3035 {
3036 /* If the input value is greater than max value of datatype,
3037 * then also kstrtou8 fails
3038 */
3039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3040 "%s: kstrtou8 failed range ", __func__);
3041 ret = -EINVAL;
3042 goto exit;
3043 }
3044
3045 if (filterType != 0 && filterType != 1)
3046 {
3047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3048 "%s: Accepted Values are 0 and 1 ", __func__);
3049 ret = -EINVAL;
3050 goto exit;
3051 }
3052 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3053 pAdapter->sessionId);
3054 }
3055#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303056 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3057 {
3058 char *dhcpPhase;
3059 dhcpPhase = command + 12;
3060 if ('1' == *dhcpPhase)
3061 {
3062 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3063 pAdapter->macAddressCurrent.bytes);
3064 }
3065 else if ('2' == *dhcpPhase)
3066 {
3067 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3068 pAdapter->macAddressCurrent.bytes);
3069 }
3070 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003071 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3072 {
3073 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3074 }
3075 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3076 {
3077 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3078 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303079 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3080 {
3081 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3082 char extra[32];
3083 tANI_U8 len = 0;
3084
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003085 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303086 (int)pCfg->nActiveMaxChnTime);
3087 if (copy_to_user(priv_data.buf, &extra, len + 1))
3088 {
3089 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3090 "%s: failed to copy data to user buffer", __func__);
3091 ret = -EFAULT;
3092 goto exit;
3093 }
3094 ret = len;
3095 }
3096 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3097 {
3098 tANI_U8 *value = command;
3099 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3100 int val = 0, temp;
3101
3102 value = value + 13;
3103 temp = kstrtou32(value, 10, &val);
3104 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3105 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3106 {
3107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3108 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3109 ret = -EFAULT;
3110 goto exit;
3111 }
3112 pCfg->nActiveMaxChnTime = val;
3113 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003114 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3115 {
3116 tANI_U8 filterType = 0;
3117 tANI_U8 *value;
3118 value = command + 9;
3119
3120 /* Convert the value from ascii to integer */
3121 ret = kstrtou8(value, 10, &filterType);
3122 if (ret < 0)
3123 {
3124 /* If the input value is greater than max value of datatype,
3125 * then also kstrtou8 fails
3126 */
3127 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3128 "%s: kstrtou8 failed range ", __func__);
3129 ret = -EINVAL;
3130 goto exit;
3131 }
3132 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3133 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3134 {
3135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3136 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3137 " 2-Sink ", __func__);
3138 ret = -EINVAL;
3139 goto exit;
3140 }
3141 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3142 pHddCtx->drvr_miracast = filterType;
3143 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3144 }
Leo Chang614d2072013-08-22 14:59:44 -07003145 else if (strncmp(command, "SETMCRATE", 9) == 0)
3146 {
3147 int rc;
3148 tANI_U8 *value = command;
3149 int targetRate;
3150
3151 /* Only valid for SAP mode */
3152 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3153 {
3154 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3155 "%s: SAP mode is not running", __func__);
3156 ret = -EFAULT;
3157 goto exit;
3158 }
3159
3160 /* Move pointer to ahead of SETMCRATE<delimiter> */
3161 /* input value is in units of hundred kbps */
3162 value = value + 10;
3163 /* Convert the value from ascii to integer, decimal base */
3164 ret = kstrtouint(value, 10, &targetRate);
3165
3166 rc = hdd_hostapd_set_mc_rate(pAdapter, targetRate);
3167 if (rc)
3168 {
3169 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3170 "%s: Set MC Rate Fail %d", __func__, rc);
3171 ret = -EFAULT;
3172 goto exit;
3173 }
3174 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303175#ifdef FEATURE_WLAN_BATCH_SCAN
3176 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3177 {
3178 char extra[32];
3179 tANI_U8 len = 0;
3180 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3181
3182 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3183 {
3184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3185 "%s: Batch scan feature is not supported by FW", __func__);
3186 ret = -EINVAL;
3187 goto exit;
3188 }
3189
3190 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3191 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3192 {
3193 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3194 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3195 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3196 " mode",
3197 pAdapter->device_mode);
3198 ret = -EINVAL;
3199 goto exit;
3200 }
3201
3202 len = snprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
3203 version);
3204 if (copy_to_user(priv_data.buf, &extra, len + 1))
3205 {
3206 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3207 "%s: failed to copy data to user buffer", __func__);
3208 ret = -EFAULT;
3209 goto exit;
3210 }
3211 ret = HDD_BATCH_SCAN_VERSION;
3212 }
3213 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3214 {
3215 int status;
3216 tANI_U8 *value = (command + 16);
3217 eHalStatus halStatus;
3218 unsigned long rc;
3219 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3220 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3221
3222 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3223 {
3224 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3225 "%s: Batch scan feature is not supported by FW", __func__);
3226 ret = -EINVAL;
3227 goto exit;
3228 }
3229
Rajeev Kumar20140c12013-10-21 19:39:02 -07003230
Rajeev79dbe4c2013-10-05 11:03:42 +05303231 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3232 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3233 {
3234 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003235 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303236 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3237 pAdapter->device_mode);
3238 ret = -EINVAL;
3239 goto exit;
3240 }
3241
Rajeev Kumar20140c12013-10-21 19:39:02 -07003242
Rajeev79dbe4c2013-10-05 11:03:42 +05303243 status = hdd_parse_set_batchscan_command(value, pReq);
3244 if (status)
3245 {
3246 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003247 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303248 ret = -EINVAL;
3249 goto exit;
3250 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003251
3252
Rajeev79dbe4c2013-10-05 11:03:42 +05303253 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3254 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3255 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3256 pAdapter);
3257
3258 if ( eHAL_STATUS_SUCCESS == halStatus )
3259 {
3260 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3261 "sme_SetBatchScanReq returned success halStatus %d",
3262 halStatus);
3263 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3264 {
3265 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3266 rc = wait_for_completion_timeout(
3267 &pAdapter->hdd_set_batch_scan_req_var,
3268 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3269 if (0 == rc)
3270 {
3271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3272 "%s: Timeout waiting for set batch scan to complete",
3273 __func__);
3274 ret = -EINVAL;
3275 goto exit;
3276 }
3277 }
3278 if ( !pRsp->nScansToBatch )
3279 {
3280 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3281 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003282 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303283 ret = -EINVAL;
3284 goto exit;
3285 }
3286 /*As per the Batch Scan Framework API we should return the MIN of
3287 either MSCAN or the max # of scans firmware can cache*/
3288 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3289
Rajeev Kumar20140c12013-10-21 19:39:02 -07003290 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3291
Rajeev79dbe4c2013-10-05 11:03:42 +05303292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3293 "%s: request MSCAN %d response MSCAN %d ret %d",
3294 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3295 }
3296 else
3297 {
3298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3299 "sme_SetBatchScanReq returned failure halStatus %d",
3300 halStatus);
3301 ret = -EINVAL;
3302 goto exit;
3303 }
3304 }
3305 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3306 {
3307 eHalStatus halStatus;
3308 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3309 pInd->param = 0;
3310
3311 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3312 {
3313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3314 "%s: Batch scan feature is not supported by FW", __func__);
3315 ret = -EINVAL;
3316 goto exit;
3317 }
3318
Rajeev Kumar20140c12013-10-21 19:39:02 -07003319 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303320 {
3321 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003322 "Batch scan is not yet enabled batch scan state %d",
3323 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303324 ret = -EINVAL;
3325 goto exit;
3326 }
3327
Rajeev Kumar20140c12013-10-21 19:39:02 -07003328 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3329
Rajeev79dbe4c2013-10-05 11:03:42 +05303330 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3331 pAdapter->sessionId);
3332 if ( eHAL_STATUS_SUCCESS == halStatus )
3333 {
3334 ret = 0;
3335 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3336 "sme_StopBatchScanInd returned success halStatus %d",
3337 halStatus);
3338 }
3339 else
3340 {
3341 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3342 "sme_StopBatchScanInd returned failure halStatus %d",
3343 halStatus);
3344 ret = -EINVAL;
3345 goto exit;
3346 }
3347 }
3348 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3349 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003350 tANI_U32 remain_len;
3351
Rajeev79dbe4c2013-10-05 11:03:42 +05303352 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3353 {
3354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3355 "%s: Batch scan feature is not supported by FW", __func__);
3356 ret = -EINVAL;
3357 goto exit;
3358 }
3359
Rajeev Kumar20140c12013-10-21 19:39:02 -07003360 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303361 {
3362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003363 "Batch scan is not yet enabled could not return results"
3364 "Batch Scan state %d",
3365 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303366 ret = -EINVAL;
3367 goto exit;
3368 }
3369
3370 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003371 remain_len = priv_data.total_len - priv_data.used_len;
3372 if (remain_len < priv_data.total_len)
3373 {
3374 /*Clear previous batch scan response data if any*/
3375 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3376 }
3377 else
3378 {
3379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3380 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003381 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003382 priv_data.total_len, priv_data.used_len, remain_len);
3383 ret = -EINVAL;
3384 goto exit;
3385 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303386 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3387 }
3388#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003389#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3390 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3391 {
3392 tANI_U8 *value = command;
3393 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3394 tANI_U8 numChannels = 0;
3395 eHalStatus status = eHAL_STATUS_SUCCESS;
3396
3397 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3398 if (eHAL_STATUS_SUCCESS != status)
3399 {
3400 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3401 "%s: Failed to parse channel list information", __func__);
3402 ret = -EINVAL;
3403 goto exit;
3404 }
3405
3406 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3407 {
3408 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3409 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3410 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3411 ret = -EINVAL;
3412 goto exit;
3413 }
3414 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3415 ChannelList,
3416 numChannels);
3417 if (eHAL_STATUS_SUCCESS != status)
3418 {
3419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3420 "%s: Failed to update channel list information", __func__);
3421 ret = -EINVAL;
3422 goto exit;
3423 }
3424 }
3425 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3426 {
3427 tANI_U8 *value = command;
3428 char extra[128] = {0};
3429 int len = 0;
3430 tANI_U8 tid = 0;
3431 hdd_station_ctx_t *pHddStaCtx = NULL;
3432 tAniTrafStrmMetrics tsmMetrics;
3433 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3434
3435 /* if not associated, return error */
3436 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3437 {
3438 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3439 ret = -EINVAL;
3440 goto exit;
3441 }
3442
3443 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3444 value = value + 12;
3445 /* Convert the value from ascii to integer */
3446 ret = kstrtou8(value, 10, &tid);
3447 if (ret < 0)
3448 {
3449 /* If the input value is greater than max value of datatype, then also
3450 kstrtou8 fails */
3451 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3452 "%s: kstrtou8 failed range [%d - %d]", __func__,
3453 TID_MIN_VALUE,
3454 TID_MAX_VALUE);
3455 ret = -EINVAL;
3456 goto exit;
3457 }
3458
3459 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3460 {
3461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3462 "tid value %d is out of range"
3463 " (Min: %d Max: %d)", tid,
3464 TID_MIN_VALUE,
3465 TID_MAX_VALUE);
3466 ret = -EINVAL;
3467 goto exit;
3468 }
3469
3470 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3471 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3472
3473 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3474 {
3475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3476 "%s: failed to get tsm stats", __func__);
3477 ret = -EFAULT;
3478 goto exit;
3479 }
3480
3481 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3482 "UplinkPktQueueDly(%d)\n"
3483 "UplinkPktQueueDlyHist[0](%d)\n"
3484 "UplinkPktQueueDlyHist[1](%d)\n"
3485 "UplinkPktQueueDlyHist[2](%d)\n"
3486 "UplinkPktQueueDlyHist[3](%d)\n"
3487 "UplinkPktTxDly(%lu)\n"
3488 "UplinkPktLoss(%d)\n"
3489 "UplinkPktCount(%d)\n"
3490 "RoamingCount(%d)\n"
3491 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3492 tsmMetrics.UplinkPktQueueDlyHist[0],
3493 tsmMetrics.UplinkPktQueueDlyHist[1],
3494 tsmMetrics.UplinkPktQueueDlyHist[2],
3495 tsmMetrics.UplinkPktQueueDlyHist[3],
3496 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3497 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3498
3499 /* Output TSM stats is of the format
3500 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3501 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
3502 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %lu %d %d %d %d", command,
3503 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3504 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3505 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3506 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3507 tsmMetrics.RoamingDly);
3508
3509 if (copy_to_user(priv_data.buf, &extra, len + 1))
3510 {
3511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3512 "%s: failed to copy data to user buffer", __func__);
3513 ret = -EFAULT;
3514 goto exit;
3515 }
3516 }
3517 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3518 {
3519 tANI_U8 *value = command;
3520 tANI_U8 *cckmIe = NULL;
3521 tANI_U8 cckmIeLen = 0;
3522 eHalStatus status = eHAL_STATUS_SUCCESS;
3523
3524 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3525 if (eHAL_STATUS_SUCCESS != status)
3526 {
3527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3528 "%s: Failed to parse cckm ie data", __func__);
3529 ret = -EINVAL;
3530 goto exit;
3531 }
3532
3533 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3534 {
3535 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3536 "%s: CCKM Ie input length is more than max[%d]", __func__,
3537 DOT11F_IE_RSN_MAX_LEN);
3538 if (NULL != cckmIe)
3539 {
3540 vos_mem_free(cckmIe);
3541 }
3542 ret = -EINVAL;
3543 goto exit;
3544 }
3545 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3546 if (NULL != cckmIe)
3547 {
3548 vos_mem_free(cckmIe);
3549 }
3550 }
3551#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003552 else {
3553 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3554 __func__, command);
3555 }
3556
Jeff Johnson295189b2012-06-20 16:38:30 -07003557 }
3558exit:
3559 if (command)
3560 {
3561 kfree(command);
3562 }
3563 return ret;
3564}
3565
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003566
3567
3568#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3569static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3570{
3571 struct statsContext *pStatsContext = NULL;
3572 hdd_adapter_t *pAdapter = NULL;
3573
3574 if (NULL == pContext)
3575 {
3576 hddLog(VOS_TRACE_LEVEL_ERROR,
3577 "%s: Bad param, pContext [%p]",
3578 __func__, pContext);
3579 return;
3580 }
3581
3582 /* there is a race condition that exists between this callback function
3583 and the caller since the caller could time out either before or
3584 while this code is executing. we'll assume the timeout hasn't
3585 occurred, but we'll verify that right before we save our work */
3586
3587 pStatsContext = pContext;
3588 pAdapter = pStatsContext->pAdapter;
3589 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3590 {
3591 /* the caller presumably timed out so there is nothing we can do */
3592 hddLog(VOS_TRACE_LEVEL_WARN,
3593 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3594 __func__, pAdapter, pStatsContext->magic);
3595 return;
3596 }
3597
3598 /* the race is on. caller could have timed out immediately after
3599 we verified the magic, but if so, caller will wait a short time
3600 for us to copy over the tsm stats */
3601 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3602 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3603 tsmMetrics.UplinkPktQueueDlyHist,
3604 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3605 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3606 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3607 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3608 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3609 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3610 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3611
3612 /* and notify the caller */
3613 complete(&pStatsContext->completion);
3614}
3615
3616
3617
3618static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3619 tAniTrafStrmMetrics* pTsmMetrics)
3620{
3621 hdd_station_ctx_t *pHddStaCtx = NULL;
3622 eHalStatus hstatus;
3623 long lrc;
3624 struct statsContext context;
3625 hdd_context_t *pHddCtx = NULL;
3626
3627 if (NULL == pAdapter)
3628 {
3629 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3630 return VOS_STATUS_E_FAULT;
3631 }
3632
3633 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3634 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3635
3636 /* we are connected prepare our callback context */
3637 init_completion(&context.completion);
3638 context.pAdapter = pAdapter;
3639 context.magic = STATS_CONTEXT_MAGIC;
3640
3641 /* query tsm stats */
3642 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3643 pHddStaCtx->conn_info.staId[ 0 ],
3644 pHddStaCtx->conn_info.bssId,
3645 &context, pHddCtx->pvosContext, tid);
3646
3647 if (eHAL_STATUS_SUCCESS != hstatus)
3648 {
3649 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3650 return hstatus;
3651 }
3652 else
3653 {
3654 /* request was sent -- wait for the response */
3655 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3656 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3657 /* either we have a response or we timed out
3658 either way, first invalidate our magic */
3659 context.magic = 0;
3660 if (lrc <= 0)
3661 {
3662 hddLog(VOS_TRACE_LEVEL_ERROR,
3663 "%s: SME %s while retrieving statistics",
3664 __func__, (0 == lrc) ? "timeout" : "interrupt");
3665 /* there is a race condition such that the callback
3666 function could be executing at the same time we are. of
3667 primary concern is if the callback function had already
3668 verified the "magic" but hasn't yet set the completion
3669 variable. Since the completion variable is on our
3670 stack, we'll delay just a bit to make sure the data is
3671 still valid if that is the case */
3672 msleep(50);
3673 return (VOS_STATUS_E_TIMEOUT);
3674 }
3675 }
3676 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3677 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3678 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3679 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3680 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3681 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3682 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3683 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3684 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3685 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3686
3687 return VOS_STATUS_SUCCESS;
3688}
3689#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3690
Srinivas Girigowdade697412013-02-14 16:31:48 -08003691#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3692void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3693{
3694 eCsrBand band = -1;
3695 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3696 switch (band)
3697 {
3698 case eCSR_BAND_ALL:
3699 *pBand = WLAN_HDD_UI_BAND_AUTO;
3700 break;
3701
3702 case eCSR_BAND_24:
3703 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3704 break;
3705
3706 case eCSR_BAND_5G:
3707 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3708 break;
3709
3710 default:
3711 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3712 *pBand = -1;
3713 break;
3714 }
3715}
3716
3717/**---------------------------------------------------------------------------
3718
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003719 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3720
3721 This function parses the send action frame data passed in the format
3722 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3723
Srinivas Girigowda56076852013-08-20 14:00:50 -07003724 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003725 \param - pTargetApBssid Pointer to target Ap bssid
3726 \param - pChannel Pointer to the Target AP channel
3727 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3728 \param - pBuf Pointer to data
3729 \param - pBufLen Pointer to data length
3730
3731 \return - 0 for success non-zero for failure
3732
3733 --------------------------------------------------------------------------*/
3734VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3735 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3736{
3737 tANI_U8 *inPtr = pValue;
3738 tANI_U8 *dataEnd;
3739 int tempInt;
3740 int j = 0;
3741 int i = 0;
3742 int v = 0;
3743 tANI_U8 tempBuf[32];
3744 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003745 /* 12 hexa decimal digits and 5 ':' */
3746 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003747
3748 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3749 /*no argument after the command*/
3750 if (NULL == inPtr)
3751 {
3752 return -EINVAL;
3753 }
3754
3755 /*no space after the command*/
3756 else if (SPACE_ASCII_VALUE != *inPtr)
3757 {
3758 return -EINVAL;
3759 }
3760
3761 /*removing empty spaces*/
3762 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3763
3764 /*no argument followed by spaces*/
3765 if ('\0' == *inPtr)
3766 {
3767 return -EINVAL;
3768 }
3769
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003770 v = sscanf(inPtr, "%17s", macAddress);
3771 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003772 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003773 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3774 "Invalid MAC address or All hex inputs are not read (%d)", v);
3775 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003776 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003777
3778 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
3779 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
3780 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
3781 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
3782 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
3783 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003784
3785 /* point to the next argument */
3786 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3787 /*no argument after the command*/
3788 if (NULL == inPtr) return -EINVAL;
3789
3790 /*removing empty spaces*/
3791 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3792
3793 /*no argument followed by spaces*/
3794 if ('\0' == *inPtr)
3795 {
3796 return -EINVAL;
3797 }
3798
3799 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003800 v = sscanf(inPtr, "%32s ", tempBuf);
3801 if (1 != v) return -EINVAL;
3802
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003803 v = kstrtos32(tempBuf, 10, &tempInt);
3804 if ( v < 0) return -EINVAL;
3805
3806 *pChannel = tempInt;
3807
3808 /* point to the next argument */
3809 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3810 /*no argument after the command*/
3811 if (NULL == inPtr) return -EINVAL;
3812 /*removing empty spaces*/
3813 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3814
3815 /*no argument followed by spaces*/
3816 if ('\0' == *inPtr)
3817 {
3818 return -EINVAL;
3819 }
3820
3821 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003822 v = sscanf(inPtr, "%32s ", tempBuf);
3823 if (1 != v) return -EINVAL;
3824
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003825 v = kstrtos32(tempBuf, 10, &tempInt);
3826 if ( v < 0) return -EINVAL;
3827
3828 *pDwellTime = tempInt;
3829
3830 /* point to the next argument */
3831 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
3832 /*no argument after the command*/
3833 if (NULL == inPtr) return -EINVAL;
3834 /*removing empty spaces*/
3835 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
3836
3837 /*no argument followed by spaces*/
3838 if ('\0' == *inPtr)
3839 {
3840 return -EINVAL;
3841 }
3842
3843 /* find the length of data */
3844 dataEnd = inPtr;
3845 while(('\0' != *dataEnd) )
3846 {
3847 dataEnd++;
3848 ++(*pBufLen);
3849 }
3850 if ( *pBufLen <= 0) return -EINVAL;
3851
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07003852 /* Allocate the number of bytes based on the number of input characters
3853 whether it is even or odd.
3854 if the number of input characters are even, then we need N/2 byte.
3855 if the number of input characters are odd, then we need do (N+1)/2 to
3856 compensate rounding off.
3857 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
3858 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
3859 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003860 if (NULL == *pBuf)
3861 {
3862 hddLog(VOS_TRACE_LEVEL_FATAL,
3863 "%s: vos_mem_alloc failed ", __func__);
3864 return -EINVAL;
3865 }
3866
3867 /* the buffer received from the upper layer is character buffer,
3868 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
3869 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
3870 and f0 in 3rd location */
3871 for (i = 0, j = 0; j < *pBufLen; j += 2)
3872 {
3873 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
3874 (*pBuf)[i++] = tempByte;
3875 }
3876 *pBufLen = i;
3877 return VOS_STATUS_SUCCESS;
3878}
3879
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003880/**---------------------------------------------------------------------------
3881
Srinivas Girigowdade697412013-02-14 16:31:48 -08003882 \brief hdd_parse_channellist() - HDD Parse channel list
3883
3884 This function parses the channel list passed in the format
3885 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003886 if the Number of channels (N) does not match with the actual number of channels passed
3887 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
3888 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
3889 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
3890 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08003891
3892 \param - pValue Pointer to input channel list
3893 \param - ChannelList Pointer to local output array to record channel list
3894 \param - pNumChannels Pointer to number of roam scan channels
3895
3896 \return - 0 for success non-zero for failure
3897
3898 --------------------------------------------------------------------------*/
3899VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
3900{
3901 tANI_U8 *inPtr = pValue;
3902 int tempInt;
3903 int j = 0;
3904 int v = 0;
3905 char buf[32];
3906
3907 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3908 /*no argument after the command*/
3909 if (NULL == inPtr)
3910 {
3911 return -EINVAL;
3912 }
3913
3914 /*no space after the command*/
3915 else if (SPACE_ASCII_VALUE != *inPtr)
3916 {
3917 return -EINVAL;
3918 }
3919
3920 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003921 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003922
3923 /*no argument followed by spaces*/
3924 if ('\0' == *inPtr)
3925 {
3926 return -EINVAL;
3927 }
3928
3929 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003930 v = sscanf(inPtr, "%32s ", buf);
3931 if (1 != v) return -EINVAL;
3932
Srinivas Girigowdade697412013-02-14 16:31:48 -08003933 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003934 if ((v < 0) ||
3935 (tempInt <= 0) ||
3936 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
3937 {
3938 return -EINVAL;
3939 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003940
3941 *pNumChannels = tempInt;
3942
3943 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3944 "Number of channels are: %d", *pNumChannels);
3945
3946 for (j = 0; j < (*pNumChannels); j++)
3947 {
3948 /*inPtr pointing to the beginning of first space after number of channels*/
3949 inPtr = strpbrk( inPtr, " " );
3950 /*no channel list after the number of channels argument*/
3951 if (NULL == inPtr)
3952 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003953 if (0 != j)
3954 {
3955 *pNumChannels = j;
3956 return VOS_STATUS_SUCCESS;
3957 }
3958 else
3959 {
3960 return -EINVAL;
3961 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003962 }
3963
3964 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003965 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08003966
3967 /*no channel list after the number of channels argument and spaces*/
3968 if ( '\0' == *inPtr )
3969 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07003970 if (0 != j)
3971 {
3972 *pNumChannels = j;
3973 return VOS_STATUS_SUCCESS;
3974 }
3975 else
3976 {
3977 return -EINVAL;
3978 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003979 }
3980
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07003981 v = sscanf(inPtr, "%32s ", buf);
3982 if (1 != v) return -EINVAL;
3983
Srinivas Girigowdade697412013-02-14 16:31:48 -08003984 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07003985 if ((v < 0) ||
3986 (tempInt <= 0) ||
3987 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3988 {
3989 return -EINVAL;
3990 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08003991 pChannelList[j] = tempInt;
3992
3993 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3994 "Channel %d added to preferred channel list",
3995 pChannelList[j] );
3996 }
3997
Srinivas Girigowdade697412013-02-14 16:31:48 -08003998 return VOS_STATUS_SUCCESS;
3999}
4000
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004001
4002/**---------------------------------------------------------------------------
4003
4004 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4005
4006 This function parses the reasoc command data passed in the format
4007 REASSOC<space><bssid><space><channel>
4008
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004009 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004010 \param - pTargetApBssid Pointer to target Ap bssid
4011 \param - pChannel Pointer to the Target AP channel
4012
4013 \return - 0 for success non-zero for failure
4014
4015 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004016VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4017 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004018{
4019 tANI_U8 *inPtr = pValue;
4020 int tempInt;
4021 int v = 0;
4022 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004023 /* 12 hexa decimal digits and 5 ':' */
4024 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004025
4026 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4027 /*no argument after the command*/
4028 if (NULL == inPtr)
4029 {
4030 return -EINVAL;
4031 }
4032
4033 /*no space after the command*/
4034 else if (SPACE_ASCII_VALUE != *inPtr)
4035 {
4036 return -EINVAL;
4037 }
4038
4039 /*removing empty spaces*/
4040 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4041
4042 /*no argument followed by spaces*/
4043 if ('\0' == *inPtr)
4044 {
4045 return -EINVAL;
4046 }
4047
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004048 v = sscanf(inPtr, "%17s", macAddress);
4049 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004050 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4052 "Invalid MAC address or All hex inputs are not read (%d)", v);
4053 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004054 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004055
4056 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4057 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4058 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4059 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4060 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4061 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004062
4063 /* point to the next argument */
4064 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4065 /*no argument after the command*/
4066 if (NULL == inPtr) return -EINVAL;
4067
4068 /*removing empty spaces*/
4069 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4070
4071 /*no argument followed by spaces*/
4072 if ('\0' == *inPtr)
4073 {
4074 return -EINVAL;
4075 }
4076
4077 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004078 v = sscanf(inPtr, "%32s ", tempBuf);
4079 if (1 != v) return -EINVAL;
4080
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004081 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004082 if ((v < 0) ||
4083 (tempInt <= 0) ||
4084 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4085 {
4086 return -EINVAL;
4087 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004088
4089 *pChannel = tempInt;
4090 return VOS_STATUS_SUCCESS;
4091}
4092
4093#endif
4094
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004095#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4096/**---------------------------------------------------------------------------
4097
4098 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4099
4100 This function parses the SETCCKM IE command
4101 SETCCKMIE<space><ie data>
4102
4103 \param - pValue Pointer to input data
4104 \param - pCckmIe Pointer to output cckm Ie
4105 \param - pCckmIeLen Pointer to output cckm ie length
4106
4107 \return - 0 for success non-zero for failure
4108
4109 --------------------------------------------------------------------------*/
4110VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4111 tANI_U8 *pCckmIeLen)
4112{
4113 tANI_U8 *inPtr = pValue;
4114 tANI_U8 *dataEnd;
4115 int j = 0;
4116 int i = 0;
4117 tANI_U8 tempByte = 0;
4118
4119 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4120 /*no argument after the command*/
4121 if (NULL == inPtr)
4122 {
4123 return -EINVAL;
4124 }
4125
4126 /*no space after the command*/
4127 else if (SPACE_ASCII_VALUE != *inPtr)
4128 {
4129 return -EINVAL;
4130 }
4131
4132 /*removing empty spaces*/
4133 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4134
4135 /*no argument followed by spaces*/
4136 if ('\0' == *inPtr)
4137 {
4138 return -EINVAL;
4139 }
4140
4141 /* find the length of data */
4142 dataEnd = inPtr;
4143 while(('\0' != *dataEnd) )
4144 {
4145 dataEnd++;
4146 ++(*pCckmIeLen);
4147 }
4148 if ( *pCckmIeLen <= 0) return -EINVAL;
4149
4150 /* Allocate the number of bytes based on the number of input characters
4151 whether it is even or odd.
4152 if the number of input characters are even, then we need N/2 byte.
4153 if the number of input characters are odd, then we need do (N+1)/2 to
4154 compensate rounding off.
4155 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4156 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4157 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4158 if (NULL == *pCckmIe)
4159 {
4160 hddLog(VOS_TRACE_LEVEL_FATAL,
4161 "%s: vos_mem_alloc failed ", __func__);
4162 return -EINVAL;
4163 }
4164 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4165 /* the buffer received from the upper layer is character buffer,
4166 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4167 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4168 and f0 in 3rd location */
4169 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4170 {
4171 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4172 (*pCckmIe)[i++] = tempByte;
4173 }
4174 *pCckmIeLen = i;
4175
4176 return VOS_STATUS_SUCCESS;
4177}
4178#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4179
Jeff Johnson295189b2012-06-20 16:38:30 -07004180/**---------------------------------------------------------------------------
4181
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004182 \brief hdd_is_valid_mac_address() - Validate MAC address
4183
4184 This function validates whether the given MAC address is valid or not
4185 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4186 where X is the hexa decimal digit character and separated by ':'
4187 This algorithm works even if MAC address is not separated by ':'
4188
4189 This code checks given input string mac contains exactly 12 hexadecimal digits.
4190 and a separator colon : appears in the input string only after
4191 an even number of hex digits.
4192
4193 \param - pMacAddr pointer to the input MAC address
4194 \return - 1 for valid and 0 for invalid
4195
4196 --------------------------------------------------------------------------*/
4197
4198v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4199{
4200 int xdigit = 0;
4201 int separator = 0;
4202 while (*pMacAddr)
4203 {
4204 if (isxdigit(*pMacAddr))
4205 {
4206 xdigit++;
4207 }
4208 else if (':' == *pMacAddr)
4209 {
4210 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4211 break;
4212
4213 ++separator;
4214 }
4215 else
4216 {
4217 separator = -1;
4218 /* Invalid MAC found */
4219 return 0;
4220 }
4221 ++pMacAddr;
4222 }
4223 return (xdigit == 12 && (separator == 5 || separator == 0));
4224}
4225
4226/**---------------------------------------------------------------------------
4227
Jeff Johnson295189b2012-06-20 16:38:30 -07004228 \brief hdd_open() - HDD Open function
4229
4230 This is called in response to ifconfig up
4231
4232 \param - dev Pointer to net_device structure
4233
4234 \return - 0 for success non-zero for failure
4235
4236 --------------------------------------------------------------------------*/
4237int hdd_open (struct net_device *dev)
4238{
4239 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4240 hdd_context_t *pHddCtx;
4241 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4242 VOS_STATUS status;
4243 v_BOOL_t in_standby = TRUE;
4244
4245 if (NULL == pAdapter)
4246 {
4247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004248 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004249 return -ENODEV;
4250 }
4251
4252 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4253 if (NULL == pHddCtx)
4254 {
4255 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004256 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004257 return -ENODEV;
4258 }
4259
4260 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4261 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4262 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004263 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4264 {
4265 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304266 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004267 in_standby = FALSE;
4268 break;
4269 }
4270 else
4271 {
4272 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4273 pAdapterNode = pNext;
4274 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004275 }
4276
4277 if (TRUE == in_standby)
4278 {
4279 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4280 {
4281 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4282 "wlan out of power save", __func__);
4283 return -EINVAL;
4284 }
4285 }
4286
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004287 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004288 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4289 {
4290 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004291 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004292 /* Enable TX queues only when we are connected */
4293 netif_tx_start_all_queues(dev);
4294 }
4295
4296 return 0;
4297}
4298
4299int hdd_mon_open (struct net_device *dev)
4300{
4301 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4302
4303 if(pAdapter == NULL) {
4304 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004305 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004306 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004307 }
4308
4309 netif_start_queue(dev);
4310
4311 return 0;
4312}
4313/**---------------------------------------------------------------------------
4314
4315 \brief hdd_stop() - HDD stop function
4316
4317 This is called in response to ifconfig down
4318
4319 \param - dev Pointer to net_device structure
4320
4321 \return - 0 for success non-zero for failure
4322
4323 --------------------------------------------------------------------------*/
4324
4325int hdd_stop (struct net_device *dev)
4326{
4327 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4328 hdd_context_t *pHddCtx;
4329 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4330 VOS_STATUS status;
4331 v_BOOL_t enter_standby = TRUE;
4332
4333 ENTER();
4334
4335 if (NULL == pAdapter)
4336 {
4337 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004338 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004339 return -ENODEV;
4340 }
4341
4342 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4343 if (NULL == pHddCtx)
4344 {
4345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004346 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004347 return -ENODEV;
4348 }
4349
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004350 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004351 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4352 netif_tx_disable(pAdapter->dev);
4353 netif_carrier_off(pAdapter->dev);
4354
4355
4356 /* SoftAP ifaces should never go in power save mode
4357 making sure same here. */
4358 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4359 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004360 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004361 )
4362 {
4363 /* SoftAP mode, so return from here */
4364 EXIT();
4365 return 0;
4366 }
4367
4368 /* Find if any iface is up then
4369 if any iface is up then can't put device to sleep/ power save mode. */
4370 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4371 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4372 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004373 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4374 {
4375 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304376 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004377 enter_standby = FALSE;
4378 break;
4379 }
4380 else
4381 {
4382 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4383 pAdapterNode = pNext;
4384 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004385 }
4386
4387 if (TRUE == enter_standby)
4388 {
4389 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4390 "entering standby", __func__);
4391 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4392 {
4393 /*log and return success*/
4394 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4395 "wlan in power save", __func__);
4396 }
4397 }
4398
4399 EXIT();
4400 return 0;
4401}
4402
4403/**---------------------------------------------------------------------------
4404
4405 \brief hdd_uninit() - HDD uninit function
4406
4407 This is called during the netdev unregister to uninitialize all data
4408associated with the device
4409
4410 \param - dev Pointer to net_device structure
4411
4412 \return - void
4413
4414 --------------------------------------------------------------------------*/
4415static void hdd_uninit (struct net_device *dev)
4416{
4417 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4418
4419 ENTER();
4420
4421 do
4422 {
4423 if (NULL == pAdapter)
4424 {
4425 hddLog(VOS_TRACE_LEVEL_FATAL,
4426 "%s: NULL pAdapter", __func__);
4427 break;
4428 }
4429
4430 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4431 {
4432 hddLog(VOS_TRACE_LEVEL_FATAL,
4433 "%s: Invalid magic", __func__);
4434 break;
4435 }
4436
4437 if (NULL == pAdapter->pHddCtx)
4438 {
4439 hddLog(VOS_TRACE_LEVEL_FATAL,
4440 "%s: NULL pHddCtx", __func__);
4441 break;
4442 }
4443
4444 if (dev != pAdapter->dev)
4445 {
4446 hddLog(VOS_TRACE_LEVEL_FATAL,
4447 "%s: Invalid device reference", __func__);
4448 /* we haven't validated all cases so let this go for now */
4449 }
4450
4451 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4452
4453 /* after uninit our adapter structure will no longer be valid */
4454 pAdapter->dev = NULL;
4455 pAdapter->magic = 0;
4456 } while (0);
4457
4458 EXIT();
4459}
4460
4461/**---------------------------------------------------------------------------
4462
4463 \brief hdd_release_firmware() -
4464
4465 This function calls the release firmware API to free the firmware buffer.
4466
4467 \param - pFileName Pointer to the File Name.
4468 pCtx - Pointer to the adapter .
4469
4470
4471 \return - 0 for success, non zero for failure
4472
4473 --------------------------------------------------------------------------*/
4474
4475VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4476{
4477 VOS_STATUS status = VOS_STATUS_SUCCESS;
4478 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4479 ENTER();
4480
4481
4482 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4483
4484 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4485
4486 if(pHddCtx->fw) {
4487 release_firmware(pHddCtx->fw);
4488 pHddCtx->fw = NULL;
4489 }
4490 else
4491 status = VOS_STATUS_E_FAILURE;
4492 }
4493 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4494 if(pHddCtx->nv) {
4495 release_firmware(pHddCtx->nv);
4496 pHddCtx->nv = NULL;
4497 }
4498 else
4499 status = VOS_STATUS_E_FAILURE;
4500
4501 }
4502
4503 EXIT();
4504 return status;
4505}
4506
4507/**---------------------------------------------------------------------------
4508
4509 \brief hdd_request_firmware() -
4510
4511 This function reads the firmware file using the request firmware
4512 API and returns the the firmware data and the firmware file size.
4513
4514 \param - pfileName - Pointer to the file name.
4515 - pCtx - Pointer to the adapter .
4516 - ppfw_data - Pointer to the pointer of the firmware data.
4517 - pSize - Pointer to the file size.
4518
4519 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4520
4521 --------------------------------------------------------------------------*/
4522
4523
4524VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4525{
4526 int status;
4527 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4528 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4529 ENTER();
4530
4531 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4532
4533 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4534
4535 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4536 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4537 __func__, pfileName);
4538 retval = VOS_STATUS_E_FAILURE;
4539 }
4540
4541 else {
4542 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4543 *pSize = pHddCtx->fw->size;
4544 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4545 __func__, *pSize);
4546 }
4547 }
4548 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4549
4550 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4551
4552 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4553 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4554 __func__, pfileName);
4555 retval = VOS_STATUS_E_FAILURE;
4556 }
4557
4558 else {
4559 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4560 *pSize = pHddCtx->nv->size;
4561 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4562 __func__, *pSize);
4563 }
4564 }
4565
4566 EXIT();
4567 return retval;
4568}
4569/**---------------------------------------------------------------------------
4570 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4571
4572 This is the function invoked by SME to inform the result of a full power
4573 request issued by HDD
4574
4575 \param - callbackcontext - Pointer to cookie
4576 status - result of request
4577
4578 \return - None
4579
4580--------------------------------------------------------------------------*/
4581void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4582{
4583 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4584
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004585 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004586 if(&pHddCtx->full_pwr_comp_var)
4587 {
4588 complete(&pHddCtx->full_pwr_comp_var);
4589 }
4590}
4591
4592/**---------------------------------------------------------------------------
4593
4594 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4595
4596 This is the function invoked by SME to inform the result of BMPS
4597 request issued by HDD
4598
4599 \param - callbackcontext - Pointer to cookie
4600 status - result of request
4601
4602 \return - None
4603
4604--------------------------------------------------------------------------*/
4605void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4606{
4607
4608 struct completion *completion_var = (struct completion*) callbackContext;
4609
4610 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4611 if(completion_var != NULL)
4612 {
4613 complete(completion_var);
4614 }
4615}
4616
4617/**---------------------------------------------------------------------------
4618
4619 \brief hdd_get_cfg_file_size() -
4620
4621 This function reads the configuration file using the request firmware
4622 API and returns the configuration file size.
4623
4624 \param - pCtx - Pointer to the adapter .
4625 - pFileName - Pointer to the file name.
4626 - pBufSize - Pointer to the buffer size.
4627
4628 \return - 0 for success, non zero for failure
4629
4630 --------------------------------------------------------------------------*/
4631
4632VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4633{
4634 int status;
4635 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4636
4637 ENTER();
4638
4639 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4640
4641 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4642 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4643 status = VOS_STATUS_E_FAILURE;
4644 }
4645 else {
4646 *pBufSize = pHddCtx->fw->size;
4647 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4648 release_firmware(pHddCtx->fw);
4649 pHddCtx->fw = NULL;
4650 }
4651
4652 EXIT();
4653 return VOS_STATUS_SUCCESS;
4654}
4655
4656/**---------------------------------------------------------------------------
4657
4658 \brief hdd_read_cfg_file() -
4659
4660 This function reads the configuration file using the request firmware
4661 API and returns the cfg data and the buffer size of the configuration file.
4662
4663 \param - pCtx - Pointer to the adapter .
4664 - pFileName - Pointer to the file name.
4665 - pBuffer - Pointer to the data buffer.
4666 - pBufSize - Pointer to the buffer size.
4667
4668 \return - 0 for success, non zero for failure
4669
4670 --------------------------------------------------------------------------*/
4671
4672VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4673 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4674{
4675 int status;
4676 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4677
4678 ENTER();
4679
4680 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4681
4682 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4683 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4684 return VOS_STATUS_E_FAILURE;
4685 }
4686 else {
4687 if(*pBufSize != pHddCtx->fw->size) {
4688 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4689 "file size", __func__);
4690 release_firmware(pHddCtx->fw);
4691 pHddCtx->fw = NULL;
4692 return VOS_STATUS_E_FAILURE;
4693 }
4694 else {
4695 if(pBuffer) {
4696 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4697 }
4698 release_firmware(pHddCtx->fw);
4699 pHddCtx->fw = NULL;
4700 }
4701 }
4702
4703 EXIT();
4704
4705 return VOS_STATUS_SUCCESS;
4706}
4707
4708/**---------------------------------------------------------------------------
4709
Jeff Johnson295189b2012-06-20 16:38:30 -07004710 \brief hdd_set_mac_address() -
4711
4712 This function sets the user specified mac address using
4713 the command ifconfig wlanX hw ether <mac adress>.
4714
4715 \param - dev - Pointer to the net device.
4716 - addr - Pointer to the sockaddr.
4717 \return - 0 for success, non zero for failure
4718
4719 --------------------------------------------------------------------------*/
4720
4721static int hdd_set_mac_address(struct net_device *dev, void *addr)
4722{
4723 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4724 struct sockaddr *psta_mac_addr = addr;
4725 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4726
4727 ENTER();
4728
4729 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
4730
4731#ifdef HDD_SESSIONIZE
4732 // set the MAC address though the STA ID CFG.
4733 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
4734 (v_U8_t *)&pAdapter->macAddressCurrent,
4735 sizeof( pAdapter->macAddressCurrent ),
4736 hdd_set_mac_addr_cb, VOS_FALSE );
4737#endif
4738
4739 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
4740
4741 EXIT();
4742 return halStatus;
4743}
4744
4745tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
4746{
4747 int i;
4748 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4749 {
4750 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
4751 break;
4752 }
4753
4754 if( VOS_MAX_CONCURRENCY_PERSONA == i)
4755 return NULL;
4756
4757 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
4758 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
4759}
4760
4761void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
4762{
4763 int i;
4764 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
4765 {
4766 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
4767 {
4768 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
4769 break;
4770 }
4771 }
4772 return;
4773}
4774
4775#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4776 static struct net_device_ops wlan_drv_ops = {
4777 .ndo_open = hdd_open,
4778 .ndo_stop = hdd_stop,
4779 .ndo_uninit = hdd_uninit,
4780 .ndo_start_xmit = hdd_hard_start_xmit,
4781 .ndo_tx_timeout = hdd_tx_timeout,
4782 .ndo_get_stats = hdd_stats,
4783 .ndo_do_ioctl = hdd_ioctl,
4784 .ndo_set_mac_address = hdd_set_mac_address,
4785 .ndo_select_queue = hdd_select_queue,
4786#ifdef WLAN_FEATURE_PACKET_FILTERING
4787#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
4788 .ndo_set_rx_mode = hdd_set_multicast_list,
4789#else
4790 .ndo_set_multicast_list = hdd_set_multicast_list,
4791#endif //LINUX_VERSION_CODE
4792#endif
4793 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004794 static struct net_device_ops wlan_mon_drv_ops = {
4795 .ndo_open = hdd_mon_open,
4796 .ndo_stop = hdd_stop,
4797 .ndo_uninit = hdd_uninit,
4798 .ndo_start_xmit = hdd_mon_hard_start_xmit,
4799 .ndo_tx_timeout = hdd_tx_timeout,
4800 .ndo_get_stats = hdd_stats,
4801 .ndo_do_ioctl = hdd_ioctl,
4802 .ndo_set_mac_address = hdd_set_mac_address,
4803 };
Jeff Johnson295189b2012-06-20 16:38:30 -07004804
4805#endif
4806
4807void hdd_set_station_ops( struct net_device *pWlanDev )
4808{
4809#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
4810 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN,
4811 pWlanDev->netdev_ops = &wlan_drv_ops;
4812#else
4813 pWlanDev->open = hdd_open;
4814 pWlanDev->stop = hdd_stop;
4815 pWlanDev->uninit = hdd_uninit;
4816 pWlanDev->hard_start_xmit = NULL;
4817 pWlanDev->tx_timeout = hdd_tx_timeout;
4818 pWlanDev->get_stats = hdd_stats;
4819 pWlanDev->do_ioctl = hdd_ioctl;
4820 pWlanDev->tx_queue_len = NET_DEV_TX_QUEUE_LEN;
4821 pWlanDev->set_mac_address = hdd_set_mac_address;
4822#endif
4823}
4824
Jeff Johnsoneed415b2013-01-18 16:11:20 -08004825static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07004826{
4827 struct net_device *pWlanDev = NULL;
4828 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004829 /*
4830 * cfg80211 initialization and registration....
4831 */
4832 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
4833
Jeff Johnson295189b2012-06-20 16:38:30 -07004834 if(pWlanDev != NULL)
4835 {
4836
4837 //Save the pointer to the net_device in the HDD adapter
4838 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
4839
Jeff Johnson295189b2012-06-20 16:38:30 -07004840 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
4841
4842 pAdapter->dev = pWlanDev;
4843 pAdapter->pHddCtx = pHddCtx;
4844 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
4845
4846 init_completion(&pAdapter->session_open_comp_var);
4847 init_completion(&pAdapter->session_close_comp_var);
4848 init_completion(&pAdapter->disconnect_comp_var);
4849 init_completion(&pAdapter->linkup_event_var);
4850 init_completion(&pAdapter->cancel_rem_on_chan_var);
4851 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07004852#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
4853 init_completion(&pAdapter->offchannel_tx_event);
4854#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004855 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004856#ifdef FEATURE_WLAN_TDLS
4857 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07004858 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08004859 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05304860 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08004861#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07004862 init_completion(&pHddCtx->mc_sus_event_var);
4863 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05304864 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07004865 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07004866 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07004867
Rajeev79dbe4c2013-10-05 11:03:42 +05304868#ifdef FEATURE_WLAN_BATCH_SCAN
4869 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
4870 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
4871 pAdapter->pBatchScanRsp = NULL;
4872 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07004873 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev79dbe4c2013-10-05 11:03:42 +05304874 mutex_init(&pAdapter->hdd_batch_scan_lock);
4875#endif
4876
Jeff Johnson295189b2012-06-20 16:38:30 -07004877 pAdapter->isLinkUpSvcNeeded = FALSE;
4878 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
4879 //Init the net_device structure
4880 strlcpy(pWlanDev->name, name, IFNAMSIZ);
4881
4882 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
4883 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
4884 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
4885 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
4886
4887 hdd_set_station_ops( pAdapter->dev );
4888
4889 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004890 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
4891 pAdapter->wdev.wiphy = pHddCtx->wiphy;
4892 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07004893 /* set pWlanDev's parent to underlying device */
4894 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
4895 }
4896
4897 return pAdapter;
4898}
4899
4900VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
4901{
4902 struct net_device *pWlanDev = pAdapter->dev;
4903 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4904 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4905 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4906
4907 if( rtnl_lock_held )
4908 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08004909 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07004910 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
4911 {
4912 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
4913 return VOS_STATUS_E_FAILURE;
4914 }
4915 }
4916 if (register_netdevice(pWlanDev))
4917 {
4918 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
4919 return VOS_STATUS_E_FAILURE;
4920 }
4921 }
4922 else
4923 {
4924 if(register_netdev(pWlanDev))
4925 {
4926 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
4927 return VOS_STATUS_E_FAILURE;
4928 }
4929 }
4930 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
4931
4932 return VOS_STATUS_SUCCESS;
4933}
4934
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004935static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07004936{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004937 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07004938
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004939 if (NULL == pAdapter)
4940 {
4941 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
4942 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07004943 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004944
4945 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4946 {
4947 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
4948 return eHAL_STATUS_NOT_INITIALIZED;
4949 }
4950
4951 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
4952
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004953#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004954 /* need to make sure all of our scheduled work has completed.
4955 * This callback is called from MC thread context, so it is safe to
4956 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004957 *
4958 * Even though this is called from MC thread context, if there is a faulty
4959 * work item in the system, that can hang this call forever. So flushing
4960 * this global work queue is not safe; and now we make sure that
4961 * individual work queues are stopped correctly. But the cancel work queue
4962 * is a GPL only API, so the proprietary version of the driver would still
4963 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004964 */
4965 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07004966#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07004967
4968 /* We can be blocked while waiting for scheduled work to be
4969 * flushed, and the adapter structure can potentially be freed, in
4970 * which case the magic will have been reset. So make sure the
4971 * magic is still good, and hence the adapter structure is still
4972 * valid, before signaling completion */
4973 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
4974 {
4975 complete(&pAdapter->session_close_comp_var);
4976 }
4977
Jeff Johnson295189b2012-06-20 16:38:30 -07004978 return eHAL_STATUS_SUCCESS;
4979}
4980
4981VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
4982{
4983 struct net_device *pWlanDev = pAdapter->dev;
4984 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
4985 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
4986 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4987 VOS_STATUS status = VOS_STATUS_E_FAILURE;
4988 int rc = 0;
4989
4990 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004991 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07004992 //Open a SME session for future operation
4993 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07004994 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07004995 if ( !HAL_STATUS_SUCCESS( halStatus ) )
4996 {
4997 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07004998 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07004999 halStatus, halStatus );
5000 status = VOS_STATUS_E_FAILURE;
5001 goto error_sme_open;
5002 }
5003
5004 //Block on a completion variable. Can't wait forever though.
5005 rc = wait_for_completion_interruptible_timeout(
5006 &pAdapter->session_open_comp_var,
5007 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5008 if (!rc)
5009 {
5010 hddLog(VOS_TRACE_LEVEL_FATAL,
5011 "Session is not opened within timeout period code %08d", rc );
5012 status = VOS_STATUS_E_FAILURE;
5013 goto error_sme_open;
5014 }
5015
5016 // Register wireless extensions
5017 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5018 {
5019 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005020 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005021 halStatus, halStatus );
5022 status = VOS_STATUS_E_FAILURE;
5023 goto error_register_wext;
5024 }
5025 //Safe to register the hard_start_xmit function again
5026#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5027 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5028#else
5029 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5030#endif
5031
5032 //Set the Connection State to Not Connected
5033 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5034
5035 //Set the default operation channel
5036 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5037
5038 /* Make the default Auth Type as OPEN*/
5039 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5040
5041 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5042 {
5043 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005044 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005045 status, status );
5046 goto error_init_txrx;
5047 }
5048
5049 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5050
5051 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5052 {
5053 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005054 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005055 status, status );
5056 goto error_wmm_init;
5057 }
5058
5059 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5060
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005061#ifdef FEATURE_WLAN_TDLS
5062 if(0 != wlan_hdd_tdls_init(pAdapter))
5063 {
5064 status = VOS_STATUS_E_FAILURE;
5065 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5066 goto error_tdls_init;
5067 }
5068 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5069#endif
5070
Jeff Johnson295189b2012-06-20 16:38:30 -07005071 return VOS_STATUS_SUCCESS;
5072
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005073#ifdef FEATURE_WLAN_TDLS
5074error_tdls_init:
5075 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5076 hdd_wmm_adapter_close(pAdapter);
5077#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005078error_wmm_init:
5079 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5080 hdd_deinit_tx_rx(pAdapter);
5081error_init_txrx:
5082 hdd_UnregisterWext(pWlanDev);
5083error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005084 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005085 {
5086 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005087 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005088 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005089 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005090 {
5091 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005092 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005093 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005094 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005095 }
5096}
5097error_sme_open:
5098 return status;
5099}
5100
Jeff Johnson295189b2012-06-20 16:38:30 -07005101void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5102{
5103 hdd_cfg80211_state_t *cfgState;
5104
5105 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5106
5107 if( NULL != cfgState->buf )
5108 {
5109 int rc;
5110 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5111 rc = wait_for_completion_interruptible_timeout(
5112 &pAdapter->tx_action_cnf_event,
5113 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5114 if(!rc)
5115 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005116 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005117 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5118 }
5119 }
5120 return;
5121}
Jeff Johnson295189b2012-06-20 16:38:30 -07005122
5123void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5124{
5125 ENTER();
5126 switch ( pAdapter->device_mode )
5127 {
5128 case WLAN_HDD_INFRA_STATION:
5129 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005130 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005131 {
5132 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5133 {
5134 hdd_deinit_tx_rx( pAdapter );
5135 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5136 }
5137
5138 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5139 {
5140 hdd_wmm_adapter_close( pAdapter );
5141 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5142 }
5143
Jeff Johnson295189b2012-06-20 16:38:30 -07005144 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005145#ifdef FEATURE_WLAN_TDLS
5146 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5147 {
5148 wlan_hdd_tdls_exit(pAdapter);
5149 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5150 }
5151#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005152
5153 break;
5154 }
5155
5156 case WLAN_HDD_SOFTAP:
5157 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005158 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305159
5160 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5161 {
5162 hdd_wmm_adapter_close( pAdapter );
5163 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5164 }
5165
Jeff Johnson295189b2012-06-20 16:38:30 -07005166 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005167
5168 hdd_unregister_hostapd(pAdapter);
5169 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005170 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005171 break;
5172 }
5173
5174 case WLAN_HDD_MONITOR:
5175 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005176 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005177 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5178 {
5179 hdd_deinit_tx_rx( pAdapter );
5180 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5181 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005182 if(NULL != pAdapterforTx)
5183 {
5184 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5185 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005186 break;
5187 }
5188
5189
5190 default:
5191 break;
5192 }
5193
5194 EXIT();
5195}
5196
5197void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5198{
5199 struct net_device *pWlanDev = pAdapter->dev;
5200
Rajeev79dbe4c2013-10-05 11:03:42 +05305201#ifdef FEATURE_WLAN_BATCH_SCAN
5202 tHddBatchScanRsp *pNode;
5203 tHddBatchScanRsp *pPrev;
5204 if (pAdapter)
5205 {
5206 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5207 pNode = pAdapter->pBatchScanRsp;
5208 while (pNode)
5209 {
5210 pPrev = pNode;
5211 pNode = pNode->pNext;
5212 vos_mem_free((v_VOID_t * )pPrev);
5213 }
5214 pAdapter->pBatchScanRsp = NULL;
5215 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5216 }
5217#endif
5218
Jeff Johnson295189b2012-06-20 16:38:30 -07005219 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5220 if( rtnl_held )
5221 {
5222 unregister_netdevice(pWlanDev);
5223 }
5224 else
5225 {
5226 unregister_netdev(pWlanDev);
5227 }
5228 // note that the pAdapter is no longer valid at this point
5229 // since the memory has been reclaimed
5230 }
5231
5232}
5233
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005234void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5235{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305236 VOS_STATUS status;
5237 hdd_adapter_t *pAdapter = NULL;
5238 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005239
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305240 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005241
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305242 /*loop through all adapters.*/
5243 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005244 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305245 pAdapter = pAdapterNode->pAdapter;
5246 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5247 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005248
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305249 { // we skip this registration for modes other than STA and P2P client modes.
5250 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5251 pAdapterNode = pNext;
5252 continue;
5253 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005254
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305255 //Apply Dynamic DTIM For P2P
5256 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5257 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5258 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5259 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5260 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5261 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5262 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5263 (eConnectionState_Associated ==
5264 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5265 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5266 {
5267 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005268
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305269 powerRequest.uIgnoreDTIM = 1;
5270 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5271
5272 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5273 {
5274 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5275 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5276 }
5277 else
5278 {
5279 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5280 }
5281
5282 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5283 * specified during Enter/Exit BMPS when LCD off*/
5284 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5285 NULL, eANI_BOOLEAN_FALSE);
5286 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5287 NULL, eANI_BOOLEAN_FALSE);
5288
5289 /* switch to the DTIM specified in cfg.ini */
5290 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5291 "Switch to DTIM %d", powerRequest.uListenInterval);
5292 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5293 break;
5294
5295 }
5296
5297 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5298 pAdapterNode = pNext;
5299 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005300}
5301
5302void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5303{
5304 /*Switch back to DTIM 1*/
5305 tSirSetPowerParamsReq powerRequest = { 0 };
5306
5307 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5308 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005309 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005310
5311 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5312 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5313 NULL, eANI_BOOLEAN_FALSE);
5314 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5315 NULL, eANI_BOOLEAN_FALSE);
5316
5317 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5318 "Switch to DTIM%d",powerRequest.uListenInterval);
5319 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5320
5321}
5322
Jeff Johnson295189b2012-06-20 16:38:30 -07005323VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5324{
5325 VOS_STATUS status = VOS_STATUS_SUCCESS;
5326
5327 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5328 {
5329 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5330 }
5331
5332 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5333 {
5334 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5335 }
5336
5337 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5338 {
5339 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5340 }
5341
5342 return status;
5343}
5344
5345VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5346{
5347 hdd_adapter_t *pAdapter = NULL;
5348 eHalStatus halStatus;
5349 VOS_STATUS status = VOS_STATUS_E_INVAL;
5350 v_BOOL_t disableBmps = FALSE;
5351 v_BOOL_t disableImps = FALSE;
5352
5353 switch(session_type)
5354 {
5355 case WLAN_HDD_INFRA_STATION:
5356 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005357 case WLAN_HDD_P2P_CLIENT:
5358 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005359 //Exit BMPS -> Is Sta/P2P Client is already connected
5360 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5361 if((NULL != pAdapter)&&
5362 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5363 {
5364 disableBmps = TRUE;
5365 }
5366
5367 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5368 if((NULL != pAdapter)&&
5369 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5370 {
5371 disableBmps = TRUE;
5372 }
5373
5374 //Exit both Bmps and Imps incase of Go/SAP Mode
5375 if((WLAN_HDD_SOFTAP == session_type) ||
5376 (WLAN_HDD_P2P_GO == session_type))
5377 {
5378 disableBmps = TRUE;
5379 disableImps = TRUE;
5380 }
5381
5382 if(TRUE == disableImps)
5383 {
5384 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5385 {
5386 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5387 }
5388 }
5389
5390 if(TRUE == disableBmps)
5391 {
5392 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5393 {
5394 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5395
5396 if(eHAL_STATUS_SUCCESS != halStatus)
5397 {
5398 status = VOS_STATUS_E_FAILURE;
5399 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5400 VOS_ASSERT(0);
5401 return status;
5402 }
5403 }
5404
5405 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5406 {
5407 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5408
5409 if(eHAL_STATUS_SUCCESS != halStatus)
5410 {
5411 status = VOS_STATUS_E_FAILURE;
5412 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5413 VOS_ASSERT(0);
5414 return status;
5415 }
5416 }
5417 }
5418
5419 if((TRUE == disableBmps) ||
5420 (TRUE == disableImps))
5421 {
5422 /* Now, get the chip into Full Power now */
5423 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5424 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5425 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5426
5427 if(halStatus != eHAL_STATUS_SUCCESS)
5428 {
5429 if(halStatus == eHAL_STATUS_PMC_PENDING)
5430 {
5431 //Block on a completion variable. Can't wait forever though
5432 wait_for_completion_interruptible_timeout(
5433 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5434 }
5435 else
5436 {
5437 status = VOS_STATUS_E_FAILURE;
5438 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5439 VOS_ASSERT(0);
5440 return status;
5441 }
5442 }
5443
5444 status = VOS_STATUS_SUCCESS;
5445 }
5446
5447 break;
5448 }
5449 return status;
5450}
5451
5452hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005453 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005454 tANI_U8 rtnl_held )
5455{
5456 hdd_adapter_t *pAdapter = NULL;
5457 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5458 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5459 VOS_STATUS exitbmpsStatus;
5460
5461 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5462
5463 //Disable BMPS incase of Concurrency
5464 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5465
5466 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5467 {
5468 //Fail to Exit BMPS
5469 VOS_ASSERT(0);
5470 return NULL;
5471 }
5472
5473 switch(session_type)
5474 {
5475 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005476 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005477 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005478 {
5479 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5480
5481 if( NULL == pAdapter )
5482 return NULL;
5483
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305484#ifdef FEATURE_WLAN_TDLS
5485 /* A Mutex Lock is introduced while changing/initializing the mode to
5486 * protect the concurrent access for the Adapters by TDLS module.
5487 */
5488 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5489 {
5490 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5491 "%s: unable to lock list", __func__);
5492 return NULL;
5493 }
5494#endif
5495
Jeff Johnsone7245742012-09-05 17:12:55 -07005496 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5497 NL80211_IFTYPE_P2P_CLIENT:
5498 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005499
Jeff Johnson295189b2012-06-20 16:38:30 -07005500 pAdapter->device_mode = session_type;
5501
5502 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305503#ifdef FEATURE_WLAN_TDLS
5504 mutex_unlock(&pHddCtx->tdls_lock);
5505#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005506 if( VOS_STATUS_SUCCESS != status )
5507 goto err_free_netdev;
5508
5509 status = hdd_register_interface( pAdapter, rtnl_held );
5510 if( VOS_STATUS_SUCCESS != status )
5511 {
5512 hdd_deinit_adapter(pHddCtx, pAdapter);
5513 goto err_free_netdev;
5514 }
5515 //Stop the Interface TX queue.
5516 netif_tx_disable(pAdapter->dev);
5517 //netif_tx_disable(pWlanDev);
5518 netif_carrier_off(pAdapter->dev);
5519
5520 break;
5521 }
5522
Jeff Johnson295189b2012-06-20 16:38:30 -07005523 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005524 case WLAN_HDD_SOFTAP:
5525 {
5526 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5527 if( NULL == pAdapter )
5528 return NULL;
5529
Jeff Johnson295189b2012-06-20 16:38:30 -07005530 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5531 NL80211_IFTYPE_AP:
5532 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005533 pAdapter->device_mode = session_type;
5534
5535 status = hdd_init_ap_mode(pAdapter);
5536 if( VOS_STATUS_SUCCESS != status )
5537 goto err_free_netdev;
5538
5539 status = hdd_register_hostapd( pAdapter, rtnl_held );
5540 if( VOS_STATUS_SUCCESS != status )
5541 {
5542 hdd_deinit_adapter(pHddCtx, pAdapter);
5543 goto err_free_netdev;
5544 }
5545
5546 netif_tx_disable(pAdapter->dev);
5547 netif_carrier_off(pAdapter->dev);
5548
5549 hdd_set_conparam( 1 );
5550 break;
5551 }
5552 case WLAN_HDD_MONITOR:
5553 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005554 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5555 if( NULL == pAdapter )
5556 return NULL;
5557
5558 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5559 pAdapter->device_mode = session_type;
5560 status = hdd_register_interface( pAdapter, rtnl_held );
5561#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5562 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5563#else
5564 pAdapter->dev->open = hdd_mon_open;
5565 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5566#endif
5567 hdd_init_tx_rx( pAdapter );
5568 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5569 //Set adapter to be used for data tx. It will use either GO or softap.
5570 pAdapter->sessionCtx.monitor.pAdapterForTx =
5571 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005572 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5573 {
5574 pAdapter->sessionCtx.monitor.pAdapterForTx =
5575 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5576 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005577 /* This workqueue will be used to transmit management packet over
5578 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005579 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5580 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5581 return NULL;
5582 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005583
Jeff Johnson295189b2012-06-20 16:38:30 -07005584 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5585 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005586 }
5587 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005588 case WLAN_HDD_FTM:
5589 {
5590 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5591
5592 if( NULL == pAdapter )
5593 return NULL;
5594 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5595 * message while loading driver in FTM mode. */
5596 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5597 pAdapter->device_mode = session_type;
5598 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305599
5600 hdd_init_tx_rx( pAdapter );
5601
5602 //Stop the Interface TX queue.
5603 netif_tx_disable(pAdapter->dev);
5604 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005605 }
5606 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005607 default:
5608 {
5609 VOS_ASSERT(0);
5610 return NULL;
5611 }
5612 }
5613
5614
5615 if( VOS_STATUS_SUCCESS == status )
5616 {
5617 //Add it to the hdd's session list.
5618 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5619 if( NULL == pHddAdapterNode )
5620 {
5621 status = VOS_STATUS_E_NOMEM;
5622 }
5623 else
5624 {
5625 pHddAdapterNode->pAdapter = pAdapter;
5626 status = hdd_add_adapter_back ( pHddCtx,
5627 pHddAdapterNode );
5628 }
5629 }
5630
5631 if( VOS_STATUS_SUCCESS != status )
5632 {
5633 if( NULL != pAdapter )
5634 {
5635 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5636 pAdapter = NULL;
5637 }
5638 if( NULL != pHddAdapterNode )
5639 {
5640 vos_mem_free( pHddAdapterNode );
5641 }
5642
5643 goto resume_bmps;
5644 }
5645
5646 if(VOS_STATUS_SUCCESS == status)
5647 {
5648 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5649
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005650 //Initialize the WoWL service
5651 if(!hdd_init_wowl(pAdapter))
5652 {
5653 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5654 goto err_free_netdev;
5655 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005656 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005657 return pAdapter;
5658
5659err_free_netdev:
5660 free_netdev(pAdapter->dev);
5661 wlan_hdd_release_intf_addr( pHddCtx,
5662 pAdapter->macAddressCurrent.bytes );
5663
5664resume_bmps:
5665 //If bmps disabled enable it
5666 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5667 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305668 if (pHddCtx->hdd_wlan_suspended)
5669 {
5670 hdd_set_pwrparams(pHddCtx);
5671 }
5672 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005673 }
5674 return NULL;
5675}
5676
5677VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5678 tANI_U8 rtnl_held )
5679{
5680 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5681 VOS_STATUS status;
5682
5683 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5684 if( VOS_STATUS_SUCCESS != status )
5685 return status;
5686
5687 while ( pCurrent->pAdapter != pAdapter )
5688 {
5689 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5690 if( VOS_STATUS_SUCCESS != status )
5691 break;
5692
5693 pCurrent = pNext;
5694 }
5695 pAdapterNode = pCurrent;
5696 if( VOS_STATUS_SUCCESS == status )
5697 {
5698 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5699 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305700
5701#ifdef FEATURE_WLAN_TDLS
5702
5703 /* A Mutex Lock is introduced while changing/initializing the mode to
5704 * protect the concurrent access for the Adapters by TDLS module.
5705 */
5706 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5707 {
5708 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5709 "%s: unable to lock list", __func__);
5710 return VOS_STATUS_E_FAILURE;
5711 }
5712#endif
5713
Jeff Johnson295189b2012-06-20 16:38:30 -07005714 hdd_remove_adapter( pHddCtx, pAdapterNode );
5715 vos_mem_free( pAdapterNode );
5716
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305717#ifdef FEATURE_WLAN_TDLS
5718 mutex_unlock(&pHddCtx->tdls_lock);
5719#endif
5720
Jeff Johnson295189b2012-06-20 16:38:30 -07005721
5722 /* If there is a single session of STA/P2P client, re-enable BMPS */
5723 if ((!vos_concurrent_sessions_running()) &&
5724 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5725 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5726 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305727 if (pHddCtx->hdd_wlan_suspended)
5728 {
5729 hdd_set_pwrparams(pHddCtx);
5730 }
5731 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005732 }
5733
5734 return VOS_STATUS_SUCCESS;
5735 }
5736
5737 return VOS_STATUS_E_FAILURE;
5738}
5739
5740VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
5741{
5742 hdd_adapter_list_node_t *pHddAdapterNode;
5743 VOS_STATUS status;
5744
5745 ENTER();
5746
5747 do
5748 {
5749 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
5750 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
5751 {
5752 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
5753 vos_mem_free( pHddAdapterNode );
5754 }
5755 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
5756
5757 EXIT();
5758
5759 return VOS_STATUS_SUCCESS;
5760}
5761
5762void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
5763{
5764 v_U8_t addIE[1] = {0};
5765
5766 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5767 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
5768 eANI_BOOLEAN_FALSE) )
5769 {
5770 hddLog(LOGE,
5771 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
5772 }
5773
5774 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5775 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
5776 eANI_BOOLEAN_FALSE) )
5777 {
5778 hddLog(LOGE,
5779 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
5780 }
5781
5782 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
5783 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
5784 eANI_BOOLEAN_FALSE) )
5785 {
5786 hddLog(LOGE,
5787 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
5788 }
5789}
5790
5791VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5792{
5793 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5794 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
5795 union iwreq_data wrqu;
5796
5797 ENTER();
5798
5799 switch(pAdapter->device_mode)
5800 {
5801 case WLAN_HDD_INFRA_STATION:
5802 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005803 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005804 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
5805 {
5806 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
5807 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5808 pAdapter->sessionId,
5809 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
5810 else
5811 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
5812 pAdapter->sessionId,
5813 eCSR_DISCONNECT_REASON_UNSPECIFIED);
5814 //success implies disconnect command got queued up successfully
5815 if(halStatus == eHAL_STATUS_SUCCESS)
5816 {
5817 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
5818 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
5819 }
5820 memset(&wrqu, '\0', sizeof(wrqu));
5821 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
5822 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
5823 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
5824 }
5825 else
5826 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05305827 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005828 }
5829
5830 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
5831 {
5832 INIT_COMPLETION(pAdapter->session_close_comp_var);
5833 if (eHAL_STATUS_SUCCESS ==
5834 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
5835 hdd_smeCloseSessionCallback, pAdapter))
5836 {
5837 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005838 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005839 &pAdapter->session_close_comp_var,
5840 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5841 }
5842 }
5843
5844 break;
5845
5846 case WLAN_HDD_SOFTAP:
5847 case WLAN_HDD_P2P_GO:
5848 //Any softap specific cleanup here...
5849 mutex_lock(&pHddCtx->sap_lock);
5850 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
5851 {
5852 VOS_STATUS status;
5853 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
5854
5855 //Stop Bss.
5856 status = WLANSAP_StopBss(pHddCtx->pvosContext);
5857 if (VOS_IS_STATUS_SUCCESS(status))
5858 {
5859 hdd_hostapd_state_t *pHostapdState =
5860 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
5861
5862 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
5863
5864 if (!VOS_IS_STATUS_SUCCESS(status))
5865 {
5866 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005867 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005868 }
5869 }
5870 else
5871 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005872 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005873 }
5874 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
5875
5876 if (eHAL_STATUS_FAILURE ==
5877 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
5878 0, NULL, eANI_BOOLEAN_FALSE))
5879 {
5880 hddLog(LOGE,
5881 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07005882 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005883 }
5884
5885 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
5886 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
5887 eANI_BOOLEAN_FALSE) )
5888 {
5889 hddLog(LOGE,
5890 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
5891 }
5892
5893 // Reset WNI_CFG_PROBE_RSP Flags
5894 wlan_hdd_reset_prob_rspies(pAdapter);
5895 kfree(pAdapter->sessionCtx.ap.beacon);
5896 pAdapter->sessionCtx.ap.beacon = NULL;
5897 }
5898 mutex_unlock(&pHddCtx->sap_lock);
5899 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005900
Jeff Johnson295189b2012-06-20 16:38:30 -07005901 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005902#ifdef WLAN_OPEN_SOURCE
5903 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
5904#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005905 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005906
Jeff Johnson295189b2012-06-20 16:38:30 -07005907 default:
5908 break;
5909 }
5910
5911 EXIT();
5912 return VOS_STATUS_SUCCESS;
5913}
5914
5915VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
5916{
5917 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5918 VOS_STATUS status;
5919 hdd_adapter_t *pAdapter;
5920
5921 ENTER();
5922
5923 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5924
5925 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5926 {
5927 pAdapter = pAdapterNode->pAdapter;
5928 netif_tx_disable(pAdapter->dev);
5929 netif_carrier_off(pAdapter->dev);
5930
5931 hdd_stop_adapter( pHddCtx, pAdapter );
5932
5933 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5934 pAdapterNode = pNext;
5935 }
5936
5937 EXIT();
5938
5939 return VOS_STATUS_SUCCESS;
5940}
5941
5942VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
5943{
5944 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5945 VOS_STATUS status;
5946 hdd_adapter_t *pAdapter;
5947
5948 ENTER();
5949
5950 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5951
5952 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5953 {
5954 pAdapter = pAdapterNode->pAdapter;
5955 netif_tx_disable(pAdapter->dev);
5956 netif_carrier_off(pAdapter->dev);
5957
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07005958 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
5959
Jeff Johnson295189b2012-06-20 16:38:30 -07005960 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305961 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5962 {
5963 hdd_wmm_adapter_close( pAdapter );
5964 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5965 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005966
5967 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5968 pAdapterNode = pNext;
5969 }
5970
5971 EXIT();
5972
5973 return VOS_STATUS_SUCCESS;
5974}
5975
5976VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
5977{
5978 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
5979 VOS_STATUS status;
5980 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305981 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07005982
5983 ENTER();
5984
5985 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
5986
5987 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
5988 {
5989 pAdapter = pAdapterNode->pAdapter;
5990
5991 switch(pAdapter->device_mode)
5992 {
5993 case WLAN_HDD_INFRA_STATION:
5994 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005995 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05305996
5997 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
5998
Jeff Johnson295189b2012-06-20 16:38:30 -07005999 hdd_init_station_mode(pAdapter);
6000 /* Open the gates for HDD to receive Wext commands */
6001 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006002 pHddCtx->scan_info.mScanPending = FALSE;
6003 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006004
6005 //Trigger the initial scan
6006 hdd_wlan_initial_scan(pAdapter);
6007
6008 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306009 if (eConnectionState_Associated == connState ||
6010 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006011 {
6012 union iwreq_data wrqu;
6013 memset(&wrqu, '\0', sizeof(wrqu));
6014 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6015 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6016 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006017 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006018
Jeff Johnson295189b2012-06-20 16:38:30 -07006019 /* indicate disconnected event to nl80211 */
6020 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6021 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006022 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306023 else if (eConnectionState_Connecting == connState)
6024 {
6025 /*
6026 * Indicate connect failure to supplicant if we were in the
6027 * process of connecting
6028 */
6029 cfg80211_connect_result(pAdapter->dev, NULL,
6030 NULL, 0, NULL, 0,
6031 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6032 GFP_KERNEL);
6033 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006034 break;
6035
6036 case WLAN_HDD_SOFTAP:
6037 /* softAP can handle SSR */
6038 break;
6039
6040 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006041 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006042 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006043 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006044 break;
6045
6046 case WLAN_HDD_MONITOR:
6047 /* monitor interface start */
6048 break;
6049 default:
6050 break;
6051 }
6052
6053 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6054 pAdapterNode = pNext;
6055 }
6056
6057 EXIT();
6058
6059 return VOS_STATUS_SUCCESS;
6060}
6061
6062VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6063{
6064 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6065 hdd_adapter_t *pAdapter;
6066 VOS_STATUS status;
6067 v_U32_t roamId;
6068
6069 ENTER();
6070
6071 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6072
6073 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6074 {
6075 pAdapter = pAdapterNode->pAdapter;
6076
6077 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6078 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6079 {
6080 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6081 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6082
6083 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6084 init_completion(&pAdapter->disconnect_comp_var);
6085 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6086 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6087
6088 wait_for_completion_interruptible_timeout(
6089 &pAdapter->disconnect_comp_var,
6090 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6091
6092 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6093 pHddCtx->isAmpAllowed = VOS_FALSE;
6094 sme_RoamConnect(pHddCtx->hHal,
6095 pAdapter->sessionId, &(pWextState->roamProfile),
6096 &roamId);
6097 }
6098
6099 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6100 pAdapterNode = pNext;
6101 }
6102
6103 EXIT();
6104
6105 return VOS_STATUS_SUCCESS;
6106}
6107
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006108void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6109{
6110 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6111 VOS_STATUS status;
6112 hdd_adapter_t *pAdapter;
6113 hdd_station_ctx_t *pHddStaCtx;
6114 hdd_ap_ctx_t *pHddApCtx;
6115 hdd_hostapd_state_t * pHostapdState;
6116 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6117 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6118 const char *p2pMode = "DEV";
6119 const char *ccMode = "Standalone";
6120 int n;
6121
6122 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6123 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6124 {
6125 pAdapter = pAdapterNode->pAdapter;
6126 switch (pAdapter->device_mode) {
6127 case WLAN_HDD_INFRA_STATION:
6128 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6129 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6130 staChannel = pHddStaCtx->conn_info.operationChannel;
6131 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6132 }
6133 break;
6134 case WLAN_HDD_P2P_CLIENT:
6135 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6136 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6137 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6138 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6139 p2pMode = "CLI";
6140 }
6141 break;
6142 case WLAN_HDD_P2P_GO:
6143 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6144 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6145 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6146 p2pChannel = pHddApCtx->operatingChannel;
6147 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6148 }
6149 p2pMode = "GO";
6150 break;
6151 case WLAN_HDD_SOFTAP:
6152 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6153 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6154 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6155 apChannel = pHddApCtx->operatingChannel;
6156 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6157 }
6158 break;
6159 default:
6160 break;
6161 }
6162 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6163 pAdapterNode = pNext;
6164 }
6165 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6166 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6167 }
6168 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6169 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6170 if (p2pChannel > 0) {
6171 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6172 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6173 }
6174 if (apChannel > 0) {
6175 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6176 apChannel, MAC_ADDR_ARRAY(apBssid));
6177 }
6178
6179 if (p2pChannel > 0 && apChannel > 0) {
6180 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6181 }
6182}
6183
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006184bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006185{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006186 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006187}
6188
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006189/* Once SSR is disabled then it cannot be set. */
6190void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006191{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006192 if (HDD_SSR_DISABLED == isSsrRequired)
6193 return;
6194
Jeff Johnson295189b2012-06-20 16:38:30 -07006195 isSsrRequired = value;
6196}
6197
6198VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6199 hdd_adapter_list_node_t** ppAdapterNode)
6200{
6201 VOS_STATUS status;
6202 spin_lock(&pHddCtx->hddAdapters.lock);
6203 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6204 (hdd_list_node_t**) ppAdapterNode );
6205 spin_unlock(&pHddCtx->hddAdapters.lock);
6206 return status;
6207}
6208
6209VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6210 hdd_adapter_list_node_t* pAdapterNode,
6211 hdd_adapter_list_node_t** pNextAdapterNode)
6212{
6213 VOS_STATUS status;
6214 spin_lock(&pHddCtx->hddAdapters.lock);
6215 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6216 (hdd_list_node_t*) pAdapterNode,
6217 (hdd_list_node_t**)pNextAdapterNode );
6218
6219 spin_unlock(&pHddCtx->hddAdapters.lock);
6220 return status;
6221}
6222
6223VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6224 hdd_adapter_list_node_t* pAdapterNode)
6225{
6226 VOS_STATUS status;
6227 spin_lock(&pHddCtx->hddAdapters.lock);
6228 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6229 &pAdapterNode->node );
6230 spin_unlock(&pHddCtx->hddAdapters.lock);
6231 return status;
6232}
6233
6234VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6235 hdd_adapter_list_node_t** ppAdapterNode)
6236{
6237 VOS_STATUS status;
6238 spin_lock(&pHddCtx->hddAdapters.lock);
6239 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6240 (hdd_list_node_t**) ppAdapterNode );
6241 spin_unlock(&pHddCtx->hddAdapters.lock);
6242 return status;
6243}
6244
6245VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6246 hdd_adapter_list_node_t* pAdapterNode)
6247{
6248 VOS_STATUS status;
6249 spin_lock(&pHddCtx->hddAdapters.lock);
6250 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6251 (hdd_list_node_t*) pAdapterNode );
6252 spin_unlock(&pHddCtx->hddAdapters.lock);
6253 return status;
6254}
6255
6256VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6257 hdd_adapter_list_node_t* pAdapterNode)
6258{
6259 VOS_STATUS status;
6260 spin_lock(&pHddCtx->hddAdapters.lock);
6261 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6262 (hdd_list_node_t*) pAdapterNode );
6263 spin_unlock(&pHddCtx->hddAdapters.lock);
6264 return status;
6265}
6266
6267hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6268 tSirMacAddr macAddr )
6269{
6270 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6271 hdd_adapter_t *pAdapter;
6272 VOS_STATUS status;
6273
6274 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6275
6276 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6277 {
6278 pAdapter = pAdapterNode->pAdapter;
6279
6280 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6281 macAddr, sizeof(tSirMacAddr) ) )
6282 {
6283 return pAdapter;
6284 }
6285 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6286 pAdapterNode = pNext;
6287 }
6288
6289 return NULL;
6290
6291}
6292
6293hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6294{
6295 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6296 hdd_adapter_t *pAdapter;
6297 VOS_STATUS status;
6298
6299 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6300
6301 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6302 {
6303 pAdapter = pAdapterNode->pAdapter;
6304
6305 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6306 IFNAMSIZ ) )
6307 {
6308 return pAdapter;
6309 }
6310 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6311 pAdapterNode = pNext;
6312 }
6313
6314 return NULL;
6315
6316}
6317
6318hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6319{
6320 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6321 hdd_adapter_t *pAdapter;
6322 VOS_STATUS status;
6323
6324 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6325
6326 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6327 {
6328 pAdapter = pAdapterNode->pAdapter;
6329
6330 if( pAdapter && (mode == pAdapter->device_mode) )
6331 {
6332 return pAdapter;
6333 }
6334 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6335 pAdapterNode = pNext;
6336 }
6337
6338 return NULL;
6339
6340}
6341
6342//Remove this function later
6343hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6344{
6345 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6346 hdd_adapter_t *pAdapter;
6347 VOS_STATUS status;
6348
6349 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6350
6351 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6352 {
6353 pAdapter = pAdapterNode->pAdapter;
6354
6355 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6356 {
6357 return pAdapter;
6358 }
6359
6360 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6361 pAdapterNode = pNext;
6362 }
6363
6364 return NULL;
6365
6366}
6367
Jeff Johnson295189b2012-06-20 16:38:30 -07006368/**---------------------------------------------------------------------------
6369
6370 \brief hdd_set_monitor_tx_adapter() -
6371
6372 This API initializes the adapter to be used while transmitting on monitor
6373 adapter.
6374
6375 \param - pHddCtx - Pointer to the HDD context.
6376 pAdapter - Adapter that will used for TX. This can be NULL.
6377 \return - None.
6378 --------------------------------------------------------------------------*/
6379void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6380{
6381 hdd_adapter_t *pMonAdapter;
6382
6383 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6384
6385 if( NULL != pMonAdapter )
6386 {
6387 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6388 }
6389}
Jeff Johnson295189b2012-06-20 16:38:30 -07006390/**---------------------------------------------------------------------------
6391
6392 \brief hdd_select_queue() -
6393
6394 This API returns the operating channel of the requested device mode
6395
6396 \param - pHddCtx - Pointer to the HDD context.
6397 - mode - Device mode for which operating channel is required
6398 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6399 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6400 \return - channel number. "0" id the requested device is not found OR it is not connected.
6401 --------------------------------------------------------------------------*/
6402v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6403{
6404 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6405 VOS_STATUS status;
6406 hdd_adapter_t *pAdapter;
6407 v_U8_t operatingChannel = 0;
6408
6409 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6410
6411 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6412 {
6413 pAdapter = pAdapterNode->pAdapter;
6414
6415 if( mode == pAdapter->device_mode )
6416 {
6417 switch(pAdapter->device_mode)
6418 {
6419 case WLAN_HDD_INFRA_STATION:
6420 case WLAN_HDD_P2P_CLIENT:
6421 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6422 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6423 break;
6424 case WLAN_HDD_SOFTAP:
6425 case WLAN_HDD_P2P_GO:
6426 /*softap connection info */
6427 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6428 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6429 break;
6430 default:
6431 break;
6432 }
6433
6434 break; //Found the device of interest. break the loop
6435 }
6436
6437 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6438 pAdapterNode = pNext;
6439 }
6440 return operatingChannel;
6441}
6442
6443#ifdef WLAN_FEATURE_PACKET_FILTERING
6444/**---------------------------------------------------------------------------
6445
6446 \brief hdd_set_multicast_list() -
6447
6448 This used to set the multicast address list.
6449
6450 \param - dev - Pointer to the WLAN device.
6451 - skb - Pointer to OS packet (sk_buff).
6452 \return - success/fail
6453
6454 --------------------------------------------------------------------------*/
6455static void hdd_set_multicast_list(struct net_device *dev)
6456{
6457 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006458 int mc_count;
6459 int i = 0;
6460 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306461
6462 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006463 {
6464 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306465 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006466 return;
6467 }
6468
6469 if (dev->flags & IFF_ALLMULTI)
6470 {
6471 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006472 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306473 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006474 }
6475 else
6476 {
6477 mc_count = netdev_mc_count(dev);
6478 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006479 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006480 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6481 {
6482 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006483 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306484 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006485 return;
6486 }
6487
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306488 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006489
6490 netdev_for_each_mc_addr(ha, dev) {
6491 if (i == mc_count)
6492 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306493 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6494 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6495 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006496 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306497 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006498 i++;
6499 }
6500 }
6501 return;
6502}
6503#endif
6504
6505/**---------------------------------------------------------------------------
6506
6507 \brief hdd_select_queue() -
6508
6509 This function is registered with the Linux OS for network
6510 core to decide which queue to use first.
6511
6512 \param - dev - Pointer to the WLAN device.
6513 - skb - Pointer to OS packet (sk_buff).
6514 \return - ac, Queue Index/access category corresponding to UP in IP header
6515
6516 --------------------------------------------------------------------------*/
6517v_U16_t hdd_select_queue(struct net_device *dev,
6518 struct sk_buff *skb)
6519{
6520 return hdd_wmm_select_queue(dev, skb);
6521}
6522
6523
6524/**---------------------------------------------------------------------------
6525
6526 \brief hdd_wlan_initial_scan() -
6527
6528 This function triggers the initial scan
6529
6530 \param - pAdapter - Pointer to the HDD adapter.
6531
6532 --------------------------------------------------------------------------*/
6533void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6534{
6535 tCsrScanRequest scanReq;
6536 tCsrChannelInfo channelInfo;
6537 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006538 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006539 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6540
6541 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6542 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6543 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6544
6545 if(sme_Is11dSupported(pHddCtx->hHal))
6546 {
6547 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6548 if ( HAL_STATUS_SUCCESS( halStatus ) )
6549 {
6550 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6551 if( !scanReq.ChannelInfo.ChannelList )
6552 {
6553 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6554 vos_mem_free(channelInfo.ChannelList);
6555 return;
6556 }
6557 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6558 channelInfo.numOfChannels);
6559 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6560 vos_mem_free(channelInfo.ChannelList);
6561 }
6562
6563 scanReq.scanType = eSIR_PASSIVE_SCAN;
6564 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6565 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6566 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6567 }
6568 else
6569 {
6570 scanReq.scanType = eSIR_ACTIVE_SCAN;
6571 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6572 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6573 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6574 }
6575
6576 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6577 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6578 {
6579 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6580 __func__, halStatus );
6581 }
6582
6583 if(sme_Is11dSupported(pHddCtx->hHal))
6584 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6585}
6586
6587struct fullPowerContext
6588{
6589 struct completion completion;
6590 unsigned int magic;
6591};
6592#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6593
6594/**---------------------------------------------------------------------------
6595
6596 \brief hdd_full_power_callback() - HDD full power callback function
6597
6598 This is the function invoked by SME to inform the result of a full power
6599 request issued by HDD
6600
6601 \param - callbackcontext - Pointer to cookie
6602 \param - status - result of request
6603
6604 \return - None
6605
6606 --------------------------------------------------------------------------*/
6607static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6608{
6609 struct fullPowerContext *pContext = callbackContext;
6610
6611 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306612 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006613
6614 if (NULL == callbackContext)
6615 {
6616 hddLog(VOS_TRACE_LEVEL_ERROR,
6617 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006618 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006619 return;
6620 }
6621
6622 /* there is a race condition that exists between this callback function
6623 and the caller since the caller could time out either before or
6624 while this code is executing. we'll assume the timeout hasn't
6625 occurred, but we'll verify that right before we save our work */
6626
6627 if (POWER_CONTEXT_MAGIC != pContext->magic)
6628 {
6629 /* the caller presumably timed out so there is nothing we can do */
6630 hddLog(VOS_TRACE_LEVEL_WARN,
6631 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006632 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006633 return;
6634 }
6635
6636 /* the race is on. caller could have timed out immediately after
6637 we verified the magic, but if so, caller will wait a short time
6638 for us to notify the caller, so the context will stay valid */
6639 complete(&pContext->completion);
6640}
6641
6642/**---------------------------------------------------------------------------
6643
6644 \brief hdd_wlan_exit() - HDD WLAN exit function
6645
6646 This is the driver exit point (invoked during rmmod)
6647
6648 \param - pHddCtx - Pointer to the HDD Context
6649
6650 \return - None
6651
6652 --------------------------------------------------------------------------*/
6653void hdd_wlan_exit(hdd_context_t *pHddCtx)
6654{
6655 eHalStatus halStatus;
6656 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6657 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306658 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006659 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006660 struct fullPowerContext powerContext;
6661 long lrc;
6662
6663 ENTER();
6664
Jeff Johnson88ba7742013-02-27 14:36:02 -08006665 if (VOS_FTM_MODE != hdd_get_conparam())
6666 {
6667 // Unloading, restart logic is no more required.
6668 wlan_hdd_restart_deinit(pHddCtx);
6669 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006670
Jeff Johnson295189b2012-06-20 16:38:30 -07006671 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006672 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006673 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006674 {
6675 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6676 WLAN_HDD_INFRA_STATION);
6677 if (pAdapter == NULL)
6678 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6679
6680 if (pAdapter != NULL)
6681 {
6682 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6683 hdd_UnregisterWext(pAdapter->dev);
6684 }
6685 }
6686 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006687
Jeff Johnson295189b2012-06-20 16:38:30 -07006688 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006689 {
6690 wlan_hdd_ftm_close(pHddCtx);
6691 goto free_hdd_ctx;
6692 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006693 //Stop the Interface TX queue.
6694 //netif_tx_disable(pWlanDev);
6695 //netif_carrier_off(pWlanDev);
6696
Jeff Johnson295189b2012-06-20 16:38:30 -07006697 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6698 {
6699 pAdapter = hdd_get_adapter(pHddCtx,
6700 WLAN_HDD_SOFTAP);
6701 }
6702 else
6703 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006704 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006705 {
6706 pAdapter = hdd_get_adapter(pHddCtx,
6707 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006708 if (pAdapter == NULL)
6709 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006710 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006711 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006712 /* DeRegister with platform driver as client for Suspend/Resume */
6713 vosStatus = hddDeregisterPmOps(pHddCtx);
6714 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6715 {
6716 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6717 VOS_ASSERT(0);
6718 }
6719
6720 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6721 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6722 {
6723 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
6724 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006725
6726 // Cancel any outstanding scan requests. We are about to close all
6727 // of our adapters, but an adapter structure is what SME passes back
6728 // to our callback function. Hence if there are any outstanding scan
6729 // requests then there is a race condition between when the adapter
6730 // is closed and when the callback is invoked. We try to resolve that
6731 // race condition here by canceling any outstanding scans before we
6732 // close the adapters.
6733 // Note that the scans may be cancelled in an asynchronous manner, so
6734 // ideally there needs to be some kind of synchronization. Rather than
6735 // introduce a new synchronization here, we will utilize the fact that
6736 // we are about to Request Full Power, and since that is synchronized,
6737 // the expectation is that by the time Request Full Power has completed,
6738 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006739 if (NULL != pAdapter)
6740 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
6741 else
6742 hddLog(VOS_TRACE_LEVEL_ERROR,
6743 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006744
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07006745 //Stop the traffic monitor timer
6746 if ( VOS_TIMER_STATE_RUNNING ==
6747 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
6748 {
6749 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
6750 }
6751
6752 // Destroy the traffic monitor timer
6753 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
6754 &pHddCtx->tx_rx_trafficTmr)))
6755 {
6756 hddLog(VOS_TRACE_LEVEL_ERROR,
6757 "%s: Cannot deallocate Traffic monitor timer", __func__);
6758 }
6759
Jeff Johnson295189b2012-06-20 16:38:30 -07006760 //Disable IMPS/BMPS as we do not want the device to enter any power
6761 //save mode during shutdown
6762 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
6763 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
6764 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
6765
6766 //Ensure that device is in full power as we will touch H/W during vos_Stop
6767 init_completion(&powerContext.completion);
6768 powerContext.magic = POWER_CONTEXT_MAGIC;
6769
6770 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
6771 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
6772
6773 if (eHAL_STATUS_SUCCESS != halStatus)
6774 {
6775 if (eHAL_STATUS_PMC_PENDING == halStatus)
6776 {
6777 /* request was sent -- wait for the response */
6778 lrc = wait_for_completion_interruptible_timeout(
6779 &powerContext.completion,
6780 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
6781 /* either we have a response or we timed out
6782 either way, first invalidate our magic */
6783 powerContext.magic = 0;
6784 if (lrc <= 0)
6785 {
6786 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006787 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07006788 /* there is a race condition such that the callback
6789 function could be executing at the same time we are. of
6790 primary concern is if the callback function had already
6791 verified the "magic" but hasn't yet set the completion
6792 variable. Since the completion variable is on our
6793 stack, we'll delay just a bit to make sure the data is
6794 still valid if that is the case */
6795 msleep(50);
6796 }
6797 }
6798 else
6799 {
6800 hddLog(VOS_TRACE_LEVEL_ERROR,
6801 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006802 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07006803 VOS_ASSERT(0);
6804 /* continue -- need to clean up as much as possible */
6805 }
6806 }
6807
Yue Ma0d4891e2013-08-06 17:01:45 -07006808 hdd_debugfs_exit(pHddCtx);
6809
Jeff Johnson295189b2012-06-20 16:38:30 -07006810 // Unregister the Net Device Notifier
6811 unregister_netdevice_notifier(&hdd_netdev_notifier);
6812
Jeff Johnson295189b2012-06-20 16:38:30 -07006813 hdd_stop_all_adapters( pHddCtx );
6814
Jeff Johnson295189b2012-06-20 16:38:30 -07006815#ifdef WLAN_BTAMP_FEATURE
6816 vosStatus = WLANBAP_Stop(pVosContext);
6817 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6818 {
6819 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
6820 "%s: Failed to stop BAP",__func__);
6821 }
6822#endif //WLAN_BTAMP_FEATURE
6823
6824 //Stop all the modules
6825 vosStatus = vos_stop( pVosContext );
6826 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
6827 {
6828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
6829 "%s: Failed to stop VOSS",__func__);
6830 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6831 }
6832
Jeff Johnson295189b2012-06-20 16:38:30 -07006833 //Assert Deep sleep signal now to put Libra HW in lowest power state
6834 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
6835 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6836
6837 //Vote off any PMIC voltage supplies
6838 vos_chipPowerDown(NULL, NULL, NULL);
6839
6840 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
6841
Leo Chang59cdc7e2013-07-10 10:08:21 -07006842
Jeff Johnson295189b2012-06-20 16:38:30 -07006843 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07006844 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006845
6846 //Close the scheduler before calling vos_close to make sure no thread is
6847 // scheduled after the each module close is called i.e after all the data
6848 // structures are freed.
6849 vosStatus = vos_sched_close( pVosContext );
6850 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
6851 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
6852 "%s: Failed to close VOSS Scheduler",__func__);
6853 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
6854 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006855#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07006856#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
6857 /* Destroy the wake lock */
6858 wake_lock_destroy(&pHddCtx->rx_wake_lock);
6859#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08006860 /* Destroy the wake lock */
6861 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08006862#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006863
6864 //Close VOSS
6865 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
6866 vos_close(pVosContext);
6867
Jeff Johnson295189b2012-06-20 16:38:30 -07006868 //Close Watchdog
6869 if(pHddCtx->cfg_ini->fIsLogpEnabled)
6870 vos_watchdog_close(pVosContext);
6871
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306872 //Clean up HDD Nlink Service
6873 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07006874#ifdef WLAN_KD_READY_NOTIFIER
6875 nl_srv_exit(pHddCtx->ptt_pid);
6876#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306877 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07006878#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05306879
Jeff Johnson295189b2012-06-20 16:38:30 -07006880 /* Cancel the vote for XO Core ON.
6881 * This is done here to ensure there is no race condition since MC, TX and WD threads have
6882 * exited at this point
6883 */
6884 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
6885 " when WLAN is turned OFF\n");
6886 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
6887 {
6888 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
6889 " Not returning failure."
6890 " Power consumed will be high\n");
6891 }
6892
6893 hdd_close_all_adapters( pHddCtx );
6894
6895
6896 //Free up dynamically allocated members inside HDD Adapter
6897 kfree(pHddCtx->cfg_ini);
6898 pHddCtx->cfg_ini= NULL;
6899
6900 /* free the power on lock from platform driver */
6901 if (free_riva_power_on_lock("wlan"))
6902 {
6903 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
6904 __func__);
6905 }
6906
Jeff Johnson88ba7742013-02-27 14:36:02 -08006907free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07006908 /* FTM mode, WIPHY did not registered
6909 If un-register here, system crash will happen */
6910 if (VOS_FTM_MODE != hdd_get_conparam())
6911 {
6912 wiphy_unregister(wiphy) ;
6913 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006914 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07006915 if (hdd_is_ssr_required())
6916 {
6917 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07006918 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07006919 msleep(5000);
6920 }
6921 hdd_set_ssr_required (VOS_FALSE);
6922}
6923
6924
6925/**---------------------------------------------------------------------------
6926
6927 \brief hdd_update_config_from_nv() - Function to update the contents of
6928 the running configuration with parameters taken from NV storage
6929
6930 \param - pHddCtx - Pointer to the HDD global context
6931
6932 \return - VOS_STATUS_SUCCESS if successful
6933
6934 --------------------------------------------------------------------------*/
6935static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
6936{
Jeff Johnson295189b2012-06-20 16:38:30 -07006937 v_BOOL_t itemIsValid = VOS_FALSE;
6938 VOS_STATUS status;
6939 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
6940 v_U8_t macLoop;
6941
6942 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
6943 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
6944 if(status != VOS_STATUS_SUCCESS)
6945 {
6946 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
6947 return VOS_STATUS_E_FAILURE;
6948 }
6949
6950 if (itemIsValid == VOS_TRUE)
6951 {
6952 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
6953 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
6954 VOS_MAX_CONCURRENCY_PERSONA);
6955 if(status != VOS_STATUS_SUCCESS)
6956 {
6957 /* Get MAC from NV fail, not update CFG info
6958 * INI MAC value will be used for MAC setting */
6959 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
6960 return VOS_STATUS_E_FAILURE;
6961 }
6962
6963 /* If first MAC is not valid, treat all others are not valid
6964 * Then all MACs will be got from ini file */
6965 if(vos_is_macaddr_zero(&macFromNV[0]))
6966 {
6967 /* MAC address in NV file is not configured yet */
6968 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
6969 return VOS_STATUS_E_INVAL;
6970 }
6971
6972 /* Get MAC address from NV, update CFG info */
6973 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
6974 {
6975 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
6976 {
6977 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
6978 /* This MAC is not valid, skip it
6979 * This MAC will be got from ini file */
6980 }
6981 else
6982 {
6983 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
6984 (v_U8_t *)&macFromNV[macLoop].bytes[0],
6985 VOS_MAC_ADDR_SIZE);
6986 }
6987 }
6988 }
6989 else
6990 {
6991 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
6992 return VOS_STATUS_E_FAILURE;
6993 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006994
Jeff Johnson295189b2012-06-20 16:38:30 -07006995
6996 return VOS_STATUS_SUCCESS;
6997}
6998
6999/**---------------------------------------------------------------------------
7000
7001 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7002
7003 \param - pAdapter - Pointer to the HDD
7004
7005 \return - None
7006
7007 --------------------------------------------------------------------------*/
7008VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7009{
7010 eHalStatus halStatus;
7011 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307012 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007013
Jeff Johnson295189b2012-06-20 16:38:30 -07007014
7015 // Send ready indication to the HDD. This will kick off the MAC
7016 // into a 'running' state and should kick off an initial scan.
7017 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7018 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7019 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307020 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007021 "code %08d [x%08x]",__func__, halStatus, halStatus );
7022 return VOS_STATUS_E_FAILURE;
7023 }
7024
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307025 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007026 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7027 // And RIVA will crash
7028 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7029 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307030 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7031 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7032
7033
Jeff Johnson295189b2012-06-20 16:38:30 -07007034 return VOS_STATUS_SUCCESS;
7035}
7036
Jeff Johnson295189b2012-06-20 16:38:30 -07007037/* wake lock APIs for HDD */
7038void hdd_prevent_suspend(void)
7039{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007040#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007041 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007042#else
7043 wcnss_prevent_suspend();
7044#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007045}
7046
7047void hdd_allow_suspend(void)
7048{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007049#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007050 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007051#else
7052 wcnss_allow_suspend();
7053#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007054}
7055
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007056void hdd_allow_suspend_timeout(v_U32_t timeout)
7057{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007058#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007059 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007060#else
7061 /* Do nothing as there is no API in wcnss for timeout*/
7062#endif
7063}
7064
Jeff Johnson295189b2012-06-20 16:38:30 -07007065/**---------------------------------------------------------------------------
7066
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007067 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7068 information between Host and Riva
7069
7070 This function gets reported version of FW
7071 It also finds the version of Riva headers used to compile the host
7072 It compares the above two and prints a warning if they are different
7073 It gets the SW and HW version string
7074 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7075 indicating the features they support through a bitmap
7076
7077 \param - pHddCtx - Pointer to HDD context
7078
7079 \return - void
7080
7081 --------------------------------------------------------------------------*/
7082
7083void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7084{
7085
7086 tSirVersionType versionCompiled;
7087 tSirVersionType versionReported;
7088 tSirVersionString versionString;
7089 tANI_U8 fwFeatCapsMsgSupported = 0;
7090 VOS_STATUS vstatus;
7091
7092 /* retrieve and display WCNSS version information */
7093 do {
7094
7095 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7096 &versionCompiled);
7097 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7098 {
7099 hddLog(VOS_TRACE_LEVEL_FATAL,
7100 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007101 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007102 break;
7103 }
7104
7105 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7106 &versionReported);
7107 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7108 {
7109 hddLog(VOS_TRACE_LEVEL_FATAL,
7110 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007111 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007112 break;
7113 }
7114
7115 if ((versionCompiled.major != versionReported.major) ||
7116 (versionCompiled.minor != versionReported.minor) ||
7117 (versionCompiled.version != versionReported.version) ||
7118 (versionCompiled.revision != versionReported.revision))
7119 {
7120 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7121 "Host expected %u.%u.%u.%u\n",
7122 WLAN_MODULE_NAME,
7123 (int)versionReported.major,
7124 (int)versionReported.minor,
7125 (int)versionReported.version,
7126 (int)versionReported.revision,
7127 (int)versionCompiled.major,
7128 (int)versionCompiled.minor,
7129 (int)versionCompiled.version,
7130 (int)versionCompiled.revision);
7131 }
7132 else
7133 {
7134 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7135 WLAN_MODULE_NAME,
7136 (int)versionReported.major,
7137 (int)versionReported.minor,
7138 (int)versionReported.version,
7139 (int)versionReported.revision);
7140 }
7141
7142 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7143 versionString,
7144 sizeof(versionString));
7145 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7146 {
7147 hddLog(VOS_TRACE_LEVEL_FATAL,
7148 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007149 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007150 break;
7151 }
7152
7153 pr_info("%s: WCNSS software version %s\n",
7154 WLAN_MODULE_NAME, versionString);
7155
7156 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7157 versionString,
7158 sizeof(versionString));
7159 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7160 {
7161 hddLog(VOS_TRACE_LEVEL_FATAL,
7162 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007163 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007164 break;
7165 }
7166
7167 pr_info("%s: WCNSS hardware version %s\n",
7168 WLAN_MODULE_NAME, versionString);
7169
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007170 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7171 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007172 send the message only if it the riva is 1.1
7173 minor numbers for different riva branches:
7174 0 -> (1.0)Mainline Build
7175 1 -> (1.1)Mainline Build
7176 2->(1.04) Stability Build
7177 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007178 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007179 ((versionReported.minor>=1) && (versionReported.version>=1)))
7180 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7181 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007182
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007183 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007184 {
7185#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7186 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7187 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7188#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007189 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7190 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7191 {
7192 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7193 }
7194
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007195 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007196 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007197
7198 } while (0);
7199
7200}
7201
7202/**---------------------------------------------------------------------------
7203
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307204 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7205
7206 \param - pHddCtx - Pointer to the hdd context
7207
7208 \return - true if hardware supports 5GHz
7209
7210 --------------------------------------------------------------------------*/
7211static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7212{
7213 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7214 * then hardware support 5Ghz.
7215 */
7216 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7217 {
7218 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7219 return true;
7220 }
7221 else
7222 {
7223 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7224 __func__);
7225 return false;
7226 }
7227}
7228
7229
7230/**---------------------------------------------------------------------------
7231
Jeff Johnson295189b2012-06-20 16:38:30 -07007232 \brief hdd_wlan_startup() - HDD init function
7233
7234 This is the driver startup code executed once a WLAN device has been detected
7235
7236 \param - dev - Pointer to the underlying device
7237
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007238 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007239
7240 --------------------------------------------------------------------------*/
7241
7242int hdd_wlan_startup(struct device *dev )
7243{
7244 VOS_STATUS status;
7245 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007246 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007247 hdd_context_t *pHddCtx = NULL;
7248 v_CONTEXT_t pVosContext= NULL;
7249#ifdef WLAN_BTAMP_FEATURE
7250 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7251 WLANBAP_ConfigType btAmpConfig;
7252 hdd_config_t *pConfig;
7253#endif
7254 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007255 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007256
7257 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007258 /*
7259 * cfg80211: wiphy allocation
7260 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307261 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007262
7263 if(wiphy == NULL)
7264 {
7265 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007266 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007267 }
7268
7269 pHddCtx = wiphy_priv(wiphy);
7270
Jeff Johnson295189b2012-06-20 16:38:30 -07007271 //Initialize the adapter context to zeros.
7272 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7273
Jeff Johnson295189b2012-06-20 16:38:30 -07007274 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007275 hdd_prevent_suspend();
7276 pHddCtx->isLoadUnloadInProgress = TRUE;
7277
7278 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7279
7280 /*Get vos context here bcoz vos_open requires it*/
7281 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7282
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007283 if(pVosContext == NULL)
7284 {
7285 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7286 goto err_free_hdd_context;
7287 }
7288
Jeff Johnson295189b2012-06-20 16:38:30 -07007289 //Save the Global VOSS context in adapter context for future.
7290 pHddCtx->pvosContext = pVosContext;
7291
7292 //Save the adapter context in global context for future.
7293 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7294
Jeff Johnson295189b2012-06-20 16:38:30 -07007295 pHddCtx->parent_dev = dev;
7296
7297 init_completion(&pHddCtx->full_pwr_comp_var);
7298 init_completion(&pHddCtx->standby_comp_var);
7299 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007300 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007301 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307302 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007303
7304#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007305 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007306#else
7307 init_completion(&pHddCtx->driver_crda_req);
7308#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007309
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307310 spin_lock_init(&pHddCtx->schedScan_lock);
7311
Jeff Johnson295189b2012-06-20 16:38:30 -07007312 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7313
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307314#ifdef FEATURE_WLAN_TDLS
7315 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7316 * invoked by other instances also) to protect the concurrent
7317 * access for the Adapters by TDLS module.
7318 */
7319 mutex_init(&pHddCtx->tdls_lock);
7320#endif
7321
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307322 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007323 // Load all config first as TL config is needed during vos_open
7324 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7325 if(pHddCtx->cfg_ini == NULL)
7326 {
7327 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7328 goto err_free_hdd_context;
7329 }
7330
7331 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7332
7333 // Read and parse the qcom_cfg.ini file
7334 status = hdd_parse_config_ini( pHddCtx );
7335 if ( VOS_STATUS_SUCCESS != status )
7336 {
7337 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7338 __func__, WLAN_INI_FILE);
7339 goto err_config;
7340 }
7341
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307342 /* INI has been read, initialise the configuredMcastBcastFilter with
7343 * INI value as this will serve as the default value
7344 */
7345 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7346 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7347 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307348
7349 if (false == hdd_is_5g_supported(pHddCtx))
7350 {
7351 //5Ghz is not supported.
7352 if (1 != pHddCtx->cfg_ini->nBandCapability)
7353 {
7354 hddLog(VOS_TRACE_LEVEL_INFO,
7355 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7356 pHddCtx->cfg_ini->nBandCapability = 1;
7357 }
7358 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307359
7360 /* If SNR Monitoring is enabled, FW has to parse all beacons
7361 * for calcaluting and storing the average SNR, so set Nth beacon
7362 * filter to 1 to enable FW to parse all the beaocons
7363 */
7364 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7365 {
7366 /* The log level is deliberately set to WARN as overriding
7367 * nthBeaconFilter to 1 will increase power cosumption and this
7368 * might just prove helpful to detect the power issue.
7369 */
7370 hddLog(VOS_TRACE_LEVEL_WARN,
7371 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7372 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7373 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007374 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307375 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007376 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307377 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007378 {
7379 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307380 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7381 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007382 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007383
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007384 // Update VOS trace levels based upon the cfg.ini
7385 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7386 pHddCtx->cfg_ini->vosTraceEnableBAP);
7387 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7388 pHddCtx->cfg_ini->vosTraceEnableTL);
7389 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7390 pHddCtx->cfg_ini->vosTraceEnableWDI);
7391 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7392 pHddCtx->cfg_ini->vosTraceEnableHDD);
7393 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7394 pHddCtx->cfg_ini->vosTraceEnableSME);
7395 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7396 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307397 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7398 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007399 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7400 pHddCtx->cfg_ini->vosTraceEnableWDA);
7401 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7402 pHddCtx->cfg_ini->vosTraceEnableSYS);
7403 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7404 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007405 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7406 pHddCtx->cfg_ini->vosTraceEnableSAP);
7407 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7408 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007409
Jeff Johnson295189b2012-06-20 16:38:30 -07007410 // Update WDI trace levels based upon the cfg.ini
7411 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7412 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7413 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7414 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7415 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7416 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7417 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7418 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007419
Jeff Johnson88ba7742013-02-27 14:36:02 -08007420 if (VOS_FTM_MODE == hdd_get_conparam())
7421 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007422 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7423 {
7424 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7425 goto err_free_hdd_context;
7426 }
7427 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7428 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007429 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007430
Jeff Johnson88ba7742013-02-27 14:36:02 -08007431 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007432 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7433 {
7434 status = vos_watchdog_open(pVosContext,
7435 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7436
7437 if(!VOS_IS_STATUS_SUCCESS( status ))
7438 {
7439 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307440 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007441 }
7442 }
7443
7444 pHddCtx->isLogpInProgress = FALSE;
7445 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7446
Jeff Johnson295189b2012-06-20 16:38:30 -07007447 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7448 if(!VOS_IS_STATUS_SUCCESS(status))
7449 {
7450 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007451 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007452 }
7453
Amar Singhala49cbc52013-10-08 18:37:44 -07007454#ifdef CONFIG_ENABLE_LINUX_REG
7455 /* registration of wiphy dev with cfg80211 */
7456 if (0 > wlan_hdd_cfg80211_register(wiphy))
7457 {
7458 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7459 goto err_clkvote;
7460 }
7461#endif
7462
Jeff Johnson295189b2012-06-20 16:38:30 -07007463 status = vos_open( &pVosContext, 0);
7464 if ( !VOS_IS_STATUS_SUCCESS( status ))
7465 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007466 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007467 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007468 }
7469
Jeff Johnson295189b2012-06-20 16:38:30 -07007470 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7471
7472 if ( NULL == pHddCtx->hHal )
7473 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007474 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007475 goto err_vosclose;
7476 }
7477
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007478 status = vos_preStart( pHddCtx->pvosContext );
7479 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7480 {
7481 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7482 goto err_vosclose;
7483 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007484
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007485 /* Note that the vos_preStart() sequence triggers the cfg download.
7486 The cfg download must occur before we update the SME config
7487 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007488 status = hdd_set_sme_config( pHddCtx );
7489
7490 if ( VOS_STATUS_SUCCESS != status )
7491 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007492 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7493 goto err_vosclose;
7494 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007495
7496 //Initialize the WMM module
7497 status = hdd_wmm_init(pHddCtx);
7498 if (!VOS_IS_STATUS_SUCCESS(status))
7499 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007500 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007501 goto err_vosclose;
7502 }
7503
Jeff Johnson295189b2012-06-20 16:38:30 -07007504 /* In the integrated architecture we update the configuration from
7505 the INI file and from NV before vOSS has been started so that
7506 the final contents are available to send down to the cCPU */
7507
7508 // Apply the cfg.ini to cfg.dat
7509 if (FALSE == hdd_update_config_dat(pHddCtx))
7510 {
7511 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7512 goto err_vosclose;
7513 }
7514
7515 // Apply the NV to cfg.dat
7516 /* Prima Update MAC address only at here */
7517 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7518 {
7519#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7520 /* There was not a valid set of MAC Addresses in NV. See if the
7521 default addresses were modified by the cfg.ini settings. If so,
7522 we'll use them, but if not, we'll autogenerate a set of MAC
7523 addresses based upon the device serial number */
7524
7525 static const v_MACADDR_t default_address =
7526 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7527 unsigned int serialno;
7528 int i;
7529
7530 serialno = wcnss_get_serial_number();
7531 if ((0 != serialno) &&
7532 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7533 sizeof(default_address))))
7534 {
7535 /* cfg.ini has the default address, invoke autogen logic */
7536
7537 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7538 bytes of the serial number that can be used to generate
7539 the other 3 bytes of the MAC address. Mask off all but
7540 the lower 3 bytes (this will also make sure we don't
7541 overflow in the next step) */
7542 serialno &= 0x00FFFFFF;
7543
7544 /* we need a unique address for each session */
7545 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7546
7547 /* autogen all addresses */
7548 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7549 {
7550 /* start with the entire default address */
7551 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7552 /* then replace the lower 3 bytes */
7553 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7554 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7555 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7556
7557 serialno++;
7558 }
7559
7560 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7561 MAC_ADDRESS_STR,
7562 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7563 }
7564 else
7565#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7566 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007567 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007568 "%s: Invalid MAC address in NV, using MAC from ini file "
7569 MAC_ADDRESS_STR, __func__,
7570 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7571 }
7572 }
7573 {
7574 eHalStatus halStatus;
7575 // Set the MAC Address
7576 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7577 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7578 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7579 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7580
7581 if (!HAL_STATUS_SUCCESS( halStatus ))
7582 {
7583 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7584 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007585 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007586 }
7587 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007588
7589 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7590 Note: Firmware image will be read and downloaded inside vos_start API */
7591 status = vos_start( pHddCtx->pvosContext );
7592 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7593 {
7594 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7595 goto err_vosclose;
7596 }
7597
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007598 /* Exchange capability info between Host and FW and also get versioning info from FW */
7599 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007600
7601 status = hdd_post_voss_start_config( pHddCtx );
7602 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7603 {
7604 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7605 __func__);
7606 goto err_vosstop;
7607 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007608
7609#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307610 wlan_hdd_cfg80211_update_reg_info( wiphy );
7611
7612 /* registration of wiphy dev with cfg80211 */
7613 if (0 > wlan_hdd_cfg80211_register(wiphy))
7614 {
7615 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7616 goto err_vosstop;
7617 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007618#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007619
Jeff Johnson295189b2012-06-20 16:38:30 -07007620 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7621 {
7622 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7623 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7624 }
7625 else
7626 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007627 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7628 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7629 if (pAdapter != NULL)
7630 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307631 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007632 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307633 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7634 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7635 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007636
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307637 /* Generate the P2P Device Address. This consists of the device's
7638 * primary MAC address with the locally administered bit set.
7639 */
7640 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007641 }
7642 else
7643 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307644 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7645 if (p2p_dev_addr != NULL)
7646 {
7647 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7648 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7649 }
7650 else
7651 {
7652 hddLog(VOS_TRACE_LEVEL_FATAL,
7653 "%s: Failed to allocate mac_address for p2p_device",
7654 __func__);
7655 goto err_close_adapter;
7656 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007657 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007658
7659 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7660 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7661 if ( NULL == pP2pAdapter )
7662 {
7663 hddLog(VOS_TRACE_LEVEL_FATAL,
7664 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007665 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007666 goto err_close_adapter;
7667 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007668 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007669 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007670
7671 if( pAdapter == NULL )
7672 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007673 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7674 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007675 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007676
Jeff Johnson295189b2012-06-20 16:38:30 -07007677#ifdef WLAN_BTAMP_FEATURE
7678 vStatus = WLANBAP_Open(pVosContext);
7679 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7680 {
7681 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7682 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007683 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007684 }
7685
7686 vStatus = BSL_Init(pVosContext);
7687 if(!VOS_IS_STATUS_SUCCESS(vStatus))
7688 {
7689 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7690 "%s: Failed to Init BSL",__func__);
7691 goto err_bap_close;
7692 }
7693 vStatus = WLANBAP_Start(pVosContext);
7694 if (!VOS_IS_STATUS_SUCCESS(vStatus))
7695 {
7696 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7697 "%s: Failed to start TL",__func__);
7698 goto err_bap_close;
7699 }
7700
7701 pConfig = pHddCtx->cfg_ini;
7702 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
7703 status = WLANBAP_SetConfig(&btAmpConfig);
7704
7705#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07007706
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07007707#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
7708 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
7709 {
7710 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
7711 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
7712 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
7713 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
7714 }
7715#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007716#ifdef FEATURE_WLAN_SCAN_PNO
7717 /*SME must send channel update configuration to RIVA*/
7718 sme_UpdateChannelConfig(pHddCtx->hHal);
7719#endif
7720
Jeff Johnson295189b2012-06-20 16:38:30 -07007721 /* Register with platform driver as client for Suspend/Resume */
7722 status = hddRegisterPmOps(pHddCtx);
7723 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7724 {
7725 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
7726#ifdef WLAN_BTAMP_FEATURE
7727 goto err_bap_stop;
7728#else
Jeff Johnsone7245742012-09-05 17:12:55 -07007729 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007730#endif //WLAN_BTAMP_FEATURE
7731 }
7732
Yue Ma0d4891e2013-08-06 17:01:45 -07007733 /* Open debugfs interface */
7734 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
7735 {
7736 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7737 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07007738 }
7739
Jeff Johnson295189b2012-06-20 16:38:30 -07007740 /* Register TM level change handler function to the platform */
7741 status = hddDevTmRegisterNotifyCallback(pHddCtx);
7742 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7743 {
7744 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
7745 goto err_unregister_pmops;
7746 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007747
7748 /* register for riva power on lock to platform driver */
7749 if (req_riva_power_on_lock("wlan"))
7750 {
7751 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
7752 __func__);
7753 goto err_unregister_pmops;
7754 }
7755
Jeff Johnson295189b2012-06-20 16:38:30 -07007756 // register net device notifier for device change notification
7757 ret = register_netdevice_notifier(&hdd_netdev_notifier);
7758
7759 if(ret < 0)
7760 {
7761 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
7762 goto err_free_power_on_lock;
7763 }
7764
7765 //Initialize the nlink service
7766 if(nl_srv_init() != 0)
7767 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307768 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007769 goto err_reg_netdev;
7770 }
7771
Leo Chang4ce1cc52013-10-21 18:27:15 -07007772#ifdef WLAN_KD_READY_NOTIFIER
7773 pHddCtx->kd_nl_init = 1;
7774#endif /* WLAN_KD_READY_NOTIFIER */
7775
Jeff Johnson295189b2012-06-20 16:38:30 -07007776 //Initialize the BTC service
7777 if(btc_activate_service(pHddCtx) != 0)
7778 {
7779 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
7780 goto err_nl_srv;
7781 }
7782
7783#ifdef PTT_SOCK_SVC_ENABLE
7784 //Initialize the PTT service
7785 if(ptt_sock_activate_svc(pHddCtx) != 0)
7786 {
7787 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
7788 goto err_nl_srv;
7789 }
7790#endif
7791
Jeff Johnson295189b2012-06-20 16:38:30 -07007792 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007793 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007794 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07007795 /* Action frame registered in one adapter which will
7796 * applicable to all interfaces
7797 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07007798 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07007799 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007800
7801 mutex_init(&pHddCtx->sap_lock);
7802
7803 pHddCtx->isLoadUnloadInProgress = FALSE;
7804
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007805#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007806#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7807 /* Initialize the wake lcok */
7808 wake_lock_init(&pHddCtx->rx_wake_lock,
7809 WAKE_LOCK_SUSPEND,
7810 "qcom_rx_wakelock");
7811#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007812 /* Initialize the wake lcok */
7813 wake_lock_init(&pHddCtx->sap_wake_lock,
7814 WAKE_LOCK_SUSPEND,
7815 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007816#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07007817
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007818 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
7819 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07007820
7821 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7822 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05307823
Jeff Johnsone7245742012-09-05 17:12:55 -07007824 // Initialize the restart logic
7825 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05307826
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007827 //Register the traffic monitor timer now
7828 if ( pHddCtx->cfg_ini->dynSplitscan)
7829 {
7830 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
7831 VOS_TIMER_TYPE_SW,
7832 hdd_tx_rx_pkt_cnt_stat_timer_handler,
7833 (void *)pHddCtx);
7834 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007835 goto success;
7836
7837err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07007838#ifdef WLAN_KD_READY_NOTIFIER
7839 nl_srv_exit(pHddCtx->ptt_pid);
7840#else
Jeff Johnson295189b2012-06-20 16:38:30 -07007841 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007842#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07007843err_reg_netdev:
7844 unregister_netdevice_notifier(&hdd_netdev_notifier);
7845
7846err_free_power_on_lock:
7847 free_riva_power_on_lock("wlan");
7848
7849err_unregister_pmops:
7850 hddDevTmUnregisterNotifyCallback(pHddCtx);
7851 hddDeregisterPmOps(pHddCtx);
7852
Yue Ma0d4891e2013-08-06 17:01:45 -07007853 hdd_debugfs_exit(pHddCtx);
7854
Jeff Johnson295189b2012-06-20 16:38:30 -07007855#ifdef WLAN_BTAMP_FEATURE
7856err_bap_stop:
7857 WLANBAP_Stop(pVosContext);
7858#endif
7859
7860#ifdef WLAN_BTAMP_FEATURE
7861err_bap_close:
7862 WLANBAP_Close(pVosContext);
7863#endif
7864
Jeff Johnson295189b2012-06-20 16:38:30 -07007865err_close_adapter:
7866 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07007867
7868#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307869 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07007870#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007871
7872err_vosstop:
7873 vos_stop(pVosContext);
7874
Amar Singhala49cbc52013-10-08 18:37:44 -07007875err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07007876 status = vos_sched_close( pVosContext );
7877 if (!VOS_IS_STATUS_SUCCESS(status)) {
7878 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7879 "%s: Failed to close VOSS Scheduler", __func__);
7880 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
7881 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007882 vos_close(pVosContext );
7883
7884err_wiphy_unregister:
7885
7886#ifdef CONFIG_ENABLE_LINUX_REG
7887 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07007888
Jeff Johnson295189b2012-06-20 16:38:30 -07007889err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07007890#endif
7891
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007892 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007893
7894err_wdclose:
7895 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7896 vos_watchdog_close(pVosContext);
7897
Jeff Johnson295189b2012-06-20 16:38:30 -07007898err_config:
7899 kfree(pHddCtx->cfg_ini);
7900 pHddCtx->cfg_ini= NULL;
7901
7902err_free_hdd_context:
7903 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07007904 wiphy_free(wiphy) ;
7905 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007906 VOS_BUG(1);
7907
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08007908 if (hdd_is_ssr_required())
7909 {
7910 /* WDI timeout had happened during load, so SSR is needed here */
7911 subsystem_restart("wcnss");
7912 msleep(5000);
7913 }
7914 hdd_set_ssr_required (VOS_FALSE);
7915
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007916 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007917
7918success:
7919 EXIT();
7920 return 0;
7921}
7922
7923/**---------------------------------------------------------------------------
7924
Jeff Johnson32d95a32012-09-10 13:15:23 -07007925 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07007926
Jeff Johnson32d95a32012-09-10 13:15:23 -07007927 This is the driver entry point - called in different timeline depending
7928 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07007929
7930 \param - None
7931
7932 \return - 0 for success, non zero for failure
7933
7934 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07007935static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07007936{
7937 VOS_STATUS status;
7938 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007939 struct device *dev = NULL;
7940 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007941#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7942 int max_retries = 0;
7943#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007944
Gopichand Nakkalad0774962013-05-24 11:32:21 +05307945#ifdef WCONN_TRACE_KMSG_LOG_BUFF
7946 vos_wconn_trace_init();
7947#endif
7948
Jeff Johnson295189b2012-06-20 16:38:30 -07007949 ENTER();
7950
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007951#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007952 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07007953#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007954
7955 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
7956 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
7957
7958 //Power Up Libra WLAN card first if not already powered up
7959 status = vos_chipPowerUp(NULL,NULL,NULL);
7960 if (!VOS_IS_STATUS_SUCCESS(status))
7961 {
7962 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
7963 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307964#ifdef WLAN_OPEN_SOURCE
7965 wake_lock_destroy(&wlan_wake_lock);
7966#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007967 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007968 }
7969
Jeff Johnson295189b2012-06-20 16:38:30 -07007970#ifdef ANI_BUS_TYPE_PCI
7971
7972 dev = wcnss_wlan_get_device();
7973
7974#endif // ANI_BUS_TYPE_PCI
7975
7976#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007977
7978#ifdef HAVE_WCNSS_CAL_DOWNLOAD
7979 /* wait until WCNSS driver downloads NV */
7980 while (!wcnss_device_ready() && 5 >= ++max_retries) {
7981 msleep(1000);
7982 }
7983 if (max_retries >= 5) {
7984 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05307985#ifdef WLAN_OPEN_SOURCE
7986 wake_lock_destroy(&wlan_wake_lock);
7987#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07007988 return -ENODEV;
7989 }
7990#endif
7991
Jeff Johnson295189b2012-06-20 16:38:30 -07007992 dev = wcnss_wlan_get_device();
7993#endif // ANI_BUS_TYPE_PLATFORM
7994
7995
7996 do {
7997 if (NULL == dev) {
7998 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
7999 ret_status = -1;
8000 break;
8001 }
8002
8003#ifdef MEMORY_DEBUG
8004 vos_mem_init();
8005#endif
8006
8007#ifdef TIMER_MANAGER
8008 vos_timer_manager_init();
8009#endif
8010
8011 /* Preopen VOSS so that it is ready to start at least SAL */
8012 status = vos_preOpen(&pVosContext);
8013
8014 if (!VOS_IS_STATUS_SUCCESS(status))
8015 {
8016 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8017 ret_status = -1;
8018 break;
8019 }
8020
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008021#ifndef MODULE
8022 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8023 */
8024 hdd_set_conparam((v_UINT_t)con_mode);
8025#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008026
8027 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008028 if (hdd_wlan_startup(dev))
8029 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008030 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008031 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008032 vos_preClose( &pVosContext );
8033 ret_status = -1;
8034 break;
8035 }
8036
8037 /* Cancel the vote for XO Core ON
8038 * This is done here for safety purposes in case we re-initialize without turning
8039 * it OFF in any error scenario.
8040 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008041 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008042 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008043 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008044 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8045 {
8046 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
8047 " Power consumed will be high\n");
8048 }
8049 } while (0);
8050
8051 if (0 != ret_status)
8052 {
8053 //Assert Deep sleep signal now to put Libra HW in lowest power state
8054 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8055 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8056
8057 //Vote off any PMIC voltage supplies
8058 vos_chipPowerDown(NULL, NULL, NULL);
8059#ifdef TIMER_MANAGER
8060 vos_timer_exit();
8061#endif
8062#ifdef MEMORY_DEBUG
8063 vos_mem_exit();
8064#endif
8065
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008066#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008067 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008068#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008069 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8070 }
8071 else
8072 {
8073 //Send WLAN UP indication to Nlink Service
8074 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8075
8076 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008077 }
8078
8079 EXIT();
8080
8081 return ret_status;
8082}
8083
Jeff Johnson32d95a32012-09-10 13:15:23 -07008084/**---------------------------------------------------------------------------
8085
8086 \brief hdd_module_init() - Init Function
8087
8088 This is the driver entry point (invoked when module is loaded using insmod)
8089
8090 \param - None
8091
8092 \return - 0 for success, non zero for failure
8093
8094 --------------------------------------------------------------------------*/
8095#ifdef MODULE
8096static int __init hdd_module_init ( void)
8097{
8098 return hdd_driver_init();
8099}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008100#else /* #ifdef MODULE */
8101static int __init hdd_module_init ( void)
8102{
8103 /* Driver initialization is delayed to fwpath_changed_handler */
8104 return 0;
8105}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008106#endif /* #ifdef MODULE */
8107
Jeff Johnson295189b2012-06-20 16:38:30 -07008108
8109/**---------------------------------------------------------------------------
8110
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008111 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008112
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008113 This is the driver exit point (invoked when module is unloaded using rmmod
8114 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008115
8116 \param - None
8117
8118 \return - None
8119
8120 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008121static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008122{
8123 hdd_context_t *pHddCtx = NULL;
8124 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008125 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008126
8127 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8128
8129 //Get the global vos context
8130 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8131
8132 if(!pVosContext)
8133 {
8134 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8135 goto done;
8136 }
8137
8138 //Get the HDD context.
8139 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8140
8141 if(!pHddCtx)
8142 {
8143 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8144 }
8145 else
8146 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008147 while(isWDresetInProgress()) {
8148 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8149 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008150 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008151
8152 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8153 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8154 "%s:SSR never completed, fatal error", __func__);
8155 VOS_BUG(0);
8156 }
8157 }
8158
Jeff Johnson295189b2012-06-20 16:38:30 -07008159
8160 pHddCtx->isLoadUnloadInProgress = TRUE;
8161 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8162
8163 //Do all the cleanup before deregistering the driver
8164 hdd_wlan_exit(pHddCtx);
8165 }
8166
Jeff Johnson295189b2012-06-20 16:38:30 -07008167 vos_preClose( &pVosContext );
8168
8169#ifdef TIMER_MANAGER
8170 vos_timer_exit();
8171#endif
8172#ifdef MEMORY_DEBUG
8173 vos_mem_exit();
8174#endif
8175
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308176#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8177 vos_wconn_trace_exit();
8178#endif
8179
Jeff Johnson295189b2012-06-20 16:38:30 -07008180done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008181#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008182 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008183#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008184 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8185}
8186
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008187/**---------------------------------------------------------------------------
8188
8189 \brief hdd_module_exit() - Exit function
8190
8191 This is the driver exit point (invoked when module is unloaded using rmmod)
8192
8193 \param - None
8194
8195 \return - None
8196
8197 --------------------------------------------------------------------------*/
8198static void __exit hdd_module_exit(void)
8199{
8200 hdd_driver_exit();
8201}
8202
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008203#ifdef MODULE
8204static int fwpath_changed_handler(const char *kmessage,
8205 struct kernel_param *kp)
8206{
Jeff Johnson76052702013-04-16 13:55:05 -07008207 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008208}
8209
8210static int con_mode_handler(const char *kmessage,
8211 struct kernel_param *kp)
8212{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008213 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008214}
8215#else /* #ifdef MODULE */
8216/**---------------------------------------------------------------------------
8217
Jeff Johnson76052702013-04-16 13:55:05 -07008218 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008219
Jeff Johnson76052702013-04-16 13:55:05 -07008220 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008221 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008222 - invoked when module parameter fwpath is modified from userspace to signal
8223 initializing the WLAN driver or when con_mode is modified from userspace
8224 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008225
8226 \return - 0 for success, non zero for failure
8227
8228 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008229static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008230{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008231 int ret_status;
8232
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008233 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008234 ret_status = hdd_driver_init();
8235 wlan_hdd_inited = ret_status ? 0 : 1;
8236 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008237 }
8238
8239 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008240
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008241 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008242
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008243 ret_status = hdd_driver_init();
8244 wlan_hdd_inited = ret_status ? 0 : 1;
8245 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008246}
8247
Jeff Johnson295189b2012-06-20 16:38:30 -07008248/**---------------------------------------------------------------------------
8249
Jeff Johnson76052702013-04-16 13:55:05 -07008250 \brief fwpath_changed_handler() - Handler Function
8251
8252 Handle changes to the fwpath parameter
8253
8254 \return - 0 for success, non zero for failure
8255
8256 --------------------------------------------------------------------------*/
8257static int fwpath_changed_handler(const char *kmessage,
8258 struct kernel_param *kp)
8259{
8260 int ret;
8261
8262 ret = param_set_copystring(kmessage, kp);
8263 if (0 == ret)
8264 ret = kickstart_driver();
8265 return ret;
8266}
8267
8268/**---------------------------------------------------------------------------
8269
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008270 \brief con_mode_handler() -
8271
8272 Handler function for module param con_mode when it is changed by userspace
8273 Dynamically linked - do nothing
8274 Statically linked - exit and init driver, as in rmmod and insmod
8275
Jeff Johnson76052702013-04-16 13:55:05 -07008276 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008277
Jeff Johnson76052702013-04-16 13:55:05 -07008278 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008279
8280 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008281static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008282{
Jeff Johnson76052702013-04-16 13:55:05 -07008283 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008284
Jeff Johnson76052702013-04-16 13:55:05 -07008285 ret = param_set_int(kmessage, kp);
8286 if (0 == ret)
8287 ret = kickstart_driver();
8288 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008289}
8290#endif /* #ifdef MODULE */
8291
8292/**---------------------------------------------------------------------------
8293
Jeff Johnson295189b2012-06-20 16:38:30 -07008294 \brief hdd_get_conparam() -
8295
8296 This is the driver exit point (invoked when module is unloaded using rmmod)
8297
8298 \param - None
8299
8300 \return - tVOS_CON_MODE
8301
8302 --------------------------------------------------------------------------*/
8303tVOS_CON_MODE hdd_get_conparam ( void )
8304{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008305#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008306 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008307#else
8308 return (tVOS_CON_MODE)curr_con_mode;
8309#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008310}
8311void hdd_set_conparam ( v_UINT_t newParam )
8312{
8313 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008314#ifndef MODULE
8315 curr_con_mode = con_mode;
8316#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008317}
8318/**---------------------------------------------------------------------------
8319
8320 \brief hdd_softap_sta_deauth() - function
8321
8322 This to take counter measure to handle deauth req from HDD
8323
8324 \param - pAdapter - Pointer to the HDD
8325
8326 \param - enable - boolean value
8327
8328 \return - None
8329
8330 --------------------------------------------------------------------------*/
8331
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008332VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008333{
Jeff Johnson295189b2012-06-20 16:38:30 -07008334 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008335 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008336
8337 ENTER();
8338
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008339 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8340 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008341
8342 //Ignore request to deauth bcmc station
8343 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008344 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008345
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008346 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008347
8348 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008349 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008350}
8351
8352/**---------------------------------------------------------------------------
8353
8354 \brief hdd_softap_sta_disassoc() - function
8355
8356 This to take counter measure to handle deauth req from HDD
8357
8358 \param - pAdapter - Pointer to the HDD
8359
8360 \param - enable - boolean value
8361
8362 \return - None
8363
8364 --------------------------------------------------------------------------*/
8365
8366void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8367{
8368 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8369
8370 ENTER();
8371
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308372 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008373
8374 //Ignore request to disassoc bcmc station
8375 if( pDestMacAddress[0] & 0x1 )
8376 return;
8377
8378 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8379}
8380
8381void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8382{
8383 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8384
8385 ENTER();
8386
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308387 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008388
8389 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8390}
8391
Jeff Johnson295189b2012-06-20 16:38:30 -07008392/**---------------------------------------------------------------------------
8393 *
8394 * \brief hdd_get__concurrency_mode() -
8395 *
8396 *
8397 * \param - None
8398 *
8399 * \return - CONCURRENCY MODE
8400 *
8401 * --------------------------------------------------------------------------*/
8402tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8403{
8404 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8405 hdd_context_t *pHddCtx;
8406
8407 if (NULL != pVosContext)
8408 {
8409 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8410 if (NULL != pHddCtx)
8411 {
8412 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8413 }
8414 }
8415
8416 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008417 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008418 return VOS_STA;
8419}
8420
8421/* Decide whether to allow/not the apps power collapse.
8422 * Allow apps power collapse if we are in connected state.
8423 * if not, allow only if we are in IMPS */
8424v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8425{
8426 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008427 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008428 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008429 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8430 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8431 hdd_adapter_t *pAdapter = NULL;
8432 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008433 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008434
Jeff Johnson295189b2012-06-20 16:38:30 -07008435 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8436 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008437
Yathish9f22e662012-12-10 14:21:35 -08008438 concurrent_state = hdd_get_concurrency_mode();
8439
8440#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8441 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8442 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8443 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8444 return TRUE;
8445#endif
8446
Jeff Johnson295189b2012-06-20 16:38:30 -07008447 /*loop through all adapters. TBD fix for Concurrency */
8448 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8449 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8450 {
8451 pAdapter = pAdapterNode->pAdapter;
8452 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8453 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8454 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008455 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008456 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008457 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008458 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8459 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008460 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008461 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008462 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8463 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008464 return FALSE;
8465 }
8466 }
8467 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8468 pAdapterNode = pNext;
8469 }
8470 return TRUE;
8471}
8472
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008473/* Decides whether to send suspend notification to Riva
8474 * if any adapter is in BMPS; then it is required */
8475v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8476{
8477 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8478 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8479
8480 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8481 {
8482 return TRUE;
8483 }
8484 return FALSE;
8485}
8486
Jeff Johnson295189b2012-06-20 16:38:30 -07008487void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8488{
8489 switch(mode)
8490 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008491 case VOS_STA_MODE:
8492 case VOS_P2P_CLIENT_MODE:
8493 case VOS_P2P_GO_MODE:
8494 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008495 pHddCtx->concurrency_mode |= (1 << mode);
8496 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008497 break;
8498 default:
8499 break;
8500
8501 }
8502 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8503 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8504}
8505
8506
8507void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8508{
8509 switch(mode)
8510 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008511 case VOS_STA_MODE:
8512 case VOS_P2P_CLIENT_MODE:
8513 case VOS_P2P_GO_MODE:
8514 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008515 pHddCtx->no_of_sessions[mode]--;
8516 if (!(pHddCtx->no_of_sessions[mode]))
8517 pHddCtx->concurrency_mode &= (~(1 << mode));
8518 break;
8519 default:
8520 break;
8521 }
8522 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8523 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8524}
8525
Jeff Johnsone7245742012-09-05 17:12:55 -07008526/**---------------------------------------------------------------------------
8527 *
8528 * \brief wlan_hdd_restart_init
8529 *
8530 * This function initalizes restart timer/flag. An internal function.
8531 *
8532 * \param - pHddCtx
8533 *
8534 * \return - None
8535 *
8536 * --------------------------------------------------------------------------*/
8537
8538static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8539{
8540 /* Initialize */
8541 pHddCtx->hdd_restart_retries = 0;
8542 atomic_set(&pHddCtx->isRestartInProgress, 0);
8543 vos_timer_init(&pHddCtx->hdd_restart_timer,
8544 VOS_TIMER_TYPE_SW,
8545 wlan_hdd_restart_timer_cb,
8546 pHddCtx);
8547}
8548/**---------------------------------------------------------------------------
8549 *
8550 * \brief wlan_hdd_restart_deinit
8551 *
8552 * This function cleans up the resources used. An internal function.
8553 *
8554 * \param - pHddCtx
8555 *
8556 * \return - None
8557 *
8558 * --------------------------------------------------------------------------*/
8559
8560static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8561{
8562
8563 VOS_STATUS vos_status;
8564 /* Block any further calls */
8565 atomic_set(&pHddCtx->isRestartInProgress, 1);
8566 /* Cleanup */
8567 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8568 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008569 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008570 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8571 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008572 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008573
8574}
8575
8576/**---------------------------------------------------------------------------
8577 *
8578 * \brief wlan_hdd_framework_restart
8579 *
8580 * This function uses a cfg80211 API to start a framework initiated WLAN
8581 * driver module unload/load.
8582 *
8583 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8584 *
8585 *
8586 * \param - pHddCtx
8587 *
8588 * \return - VOS_STATUS_SUCCESS: Success
8589 * VOS_STATUS_E_EMPTY: Adapter is Empty
8590 * VOS_STATUS_E_NOMEM: No memory
8591
8592 * --------------------------------------------------------------------------*/
8593
8594static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8595{
8596 VOS_STATUS status = VOS_STATUS_SUCCESS;
8597 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008598 int len = (sizeof (struct ieee80211_mgmt));
8599 struct ieee80211_mgmt *mgmt = NULL;
8600
8601 /* Prepare the DEAUTH managment frame with reason code */
8602 mgmt = kzalloc(len, GFP_KERNEL);
8603 if(mgmt == NULL)
8604 {
8605 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8606 "%s: memory allocation failed (%d bytes)", __func__, len);
8607 return VOS_STATUS_E_NOMEM;
8608 }
8609 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008610
8611 /* Iterate over all adapters/devices */
8612 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8613 do
8614 {
8615 if( (status == VOS_STATUS_SUCCESS) &&
8616 pAdapterNode &&
8617 pAdapterNode->pAdapter)
8618 {
8619 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8620 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8621 pAdapterNode->pAdapter->dev->name,
8622 pAdapterNode->pAdapter->device_mode,
8623 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008624 /*
8625 * CFG80211 event to restart the driver
8626 *
8627 * 'cfg80211_send_unprot_deauth' sends a
8628 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8629 * of SME(Linux Kernel) state machine.
8630 *
8631 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8632 * the driver.
8633 *
8634 */
8635
8636 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008637 }
8638 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8639 pAdapterNode = pNext;
8640 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8641
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008642
8643 /* Free the allocated management frame */
8644 kfree(mgmt);
8645
Jeff Johnsone7245742012-09-05 17:12:55 -07008646 /* Retry until we unload or reach max count */
8647 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8648 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8649
8650 return status;
8651
8652}
8653/**---------------------------------------------------------------------------
8654 *
8655 * \brief wlan_hdd_restart_timer_cb
8656 *
8657 * Restart timer callback. An internal function.
8658 *
8659 * \param - User data:
8660 *
8661 * \return - None
8662 *
8663 * --------------------------------------------------------------------------*/
8664
8665void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
8666{
8667 hdd_context_t *pHddCtx = usrDataForCallback;
8668 wlan_hdd_framework_restart(pHddCtx);
8669 return;
8670
8671}
8672
8673
8674/**---------------------------------------------------------------------------
8675 *
8676 * \brief wlan_hdd_restart_driver
8677 *
8678 * This function sends an event to supplicant to restart the WLAN driver.
8679 *
8680 * This function is called from vos_wlanRestart.
8681 *
8682 * \param - pHddCtx
8683 *
8684 * \return - VOS_STATUS_SUCCESS: Success
8685 * VOS_STATUS_E_EMPTY: Adapter is Empty
8686 * VOS_STATUS_E_ALREADY: Request already in progress
8687
8688 * --------------------------------------------------------------------------*/
8689VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
8690{
8691 VOS_STATUS status = VOS_STATUS_SUCCESS;
8692
8693 /* A tight check to make sure reentrancy */
8694 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
8695 {
8696 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
8697 "%s: WLAN restart is already in progress", __func__);
8698
8699 return VOS_STATUS_E_ALREADY;
8700 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07008701 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08008702#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07008703 wcnss_reset_intr();
8704#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07008705
Jeff Johnsone7245742012-09-05 17:12:55 -07008706 return status;
8707}
8708
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07008709/*
8710 * API to find if there is any STA or P2P-Client is connected
8711 */
8712VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
8713{
8714 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
8715}
Jeff Johnsone7245742012-09-05 17:12:55 -07008716
Jeff Johnson295189b2012-06-20 16:38:30 -07008717//Register the module init/exit functions
8718module_init(hdd_module_init);
8719module_exit(hdd_module_exit);
8720
8721MODULE_LICENSE("Dual BSD/GPL");
8722MODULE_AUTHOR("Qualcomm Atheros, Inc.");
8723MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
8724
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008725module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
8726 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07008727
Jeff Johnson76052702013-04-16 13:55:05 -07008728module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07008729 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);