blob: af90047ac48158d68903adfc53ae67e0a90526f6 [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};
Arif Hussain66559122013-11-21 10:11:40 -0800154
155static char *country_code;
156static int enable_11d = -1;
157static int enable_dfs_chan_scan = -1;
158
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700159#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700160static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700162
Jeff Johnsone7245742012-09-05 17:12:55 -0700163/*
164 * The rate at which the driver sends RESTART event to supplicant
165 * once the function 'vos_wlanRestart()' is called
166 *
167 */
168#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
169#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700170
171/*
172 * Size of Driver command strings from upper layer
173 */
174#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
175#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
176
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700177#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
178#define TID_MIN_VALUE 0
179#define TID_MAX_VALUE 15
180static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
181 tAniTrafStrmMetrics* pTsmMetrics);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -0800182static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
183 tCsrCcxBeaconReq *pCcxBcnReq);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700184#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
185
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700186/*
187 * Driver miracast parameters 0-Disabled
188 * 1-Source, 2-Sink
189 */
190#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
191#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
192
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800193#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700194static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700195#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700196/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700197static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700198
199//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700200static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
201static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
202static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
203void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800204void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700205
Jeff Johnson295189b2012-06-20 16:38:30 -0700206v_U16_t hdd_select_queue(struct net_device *dev,
207 struct sk_buff *skb);
208
209#ifdef WLAN_FEATURE_PACKET_FILTERING
210static void hdd_set_multicast_list(struct net_device *dev);
211#endif
212
213void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700214int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700215
216extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Amar Singhal0a402232013-10-11 20:57:16 -0700217
Srinivas Girigowdade697412013-02-14 16:31:48 -0800218#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
219void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
220static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700221static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
222 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
223 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700224static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
225 tANI_U8 *pTargetApBssid,
226 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800227#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700228#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
229VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
230#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
231
Jeff Johnson295189b2012-06-20 16:38:30 -0700232static int hdd_netdev_notifier_call(struct notifier_block * nb,
233 unsigned long state,
234 void *ndev)
235{
236 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700237 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700238 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700239#ifdef WLAN_BTAMP_FEATURE
240 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700241#endif
242
243 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700244 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700245 (strncmp(dev->name, "p2p", 3)))
246 return NOTIFY_DONE;
247
248 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700249 return NOTIFY_DONE;
250
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700252 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700253
Jeff Johnson27cee452013-03-27 11:10:24 -0700254 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700255 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800256 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700257 VOS_ASSERT(0);
258 return NOTIFY_DONE;
259 }
260
Jeff Johnson27cee452013-03-27 11:10:24 -0700261 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
262 if (NULL == pHddCtx)
263 {
264 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
265 VOS_ASSERT(0);
266 return NOTIFY_DONE;
267 }
268
269 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
270 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700271
272 switch (state) {
273 case NETDEV_REGISTER:
274 break;
275
276 case NETDEV_UNREGISTER:
277 break;
278
279 case NETDEV_UP:
280 break;
281
282 case NETDEV_DOWN:
283 break;
284
285 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700286 if(TRUE == pAdapter->isLinkUpSvcNeeded)
287 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700288 break;
289
290 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700291 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700292 {
293 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800294 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530295 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700296 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800297 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700298 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
299 if(!result)
300 {
301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800302 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700303 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700304 }
305 }
306 else
307 {
308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700309 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 }
311#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700312 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700313 status = WLANBAP_StopAmp();
314 if(VOS_STATUS_SUCCESS != status )
315 {
316 pHddCtx->isAmpAllowed = VOS_TRUE;
317 hddLog(VOS_TRACE_LEVEL_FATAL,
318 "%s: Failed to stop AMP", __func__);
319 }
320 else
321 {
322 //a state m/c implementation in PAL is TBD to avoid this delay
323 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700324 if ( pHddCtx->isAmpAllowed )
325 {
326 WLANBAP_DeregisterFromHCI();
327 pHddCtx->isAmpAllowed = VOS_FALSE;
328 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700329 }
330#endif //WLAN_BTAMP_FEATURE
331 break;
332
333 default:
334 break;
335 }
336
337 return NOTIFY_DONE;
338}
339
340struct notifier_block hdd_netdev_notifier = {
341 .notifier_call = hdd_netdev_notifier_call,
342};
343
344/*---------------------------------------------------------------------------
345 * Function definitions
346 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700347void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
348void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700349//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700350static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700351#ifndef MODULE
352/* current con_mode - used only for statically linked driver
353 * con_mode is changed by userspace to indicate a mode change which will
354 * result in calling the module exit and init functions. The module
355 * exit function will clean up based on the value of con_mode prior to it
356 * being changed by userspace. So curr_con_mode records the current con_mode
357 * for exit when con_mode becomes the next mode for init
358 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700359static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700360#endif
361
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800362/**---------------------------------------------------------------------------
363
364 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
365
366 Called immediately after the cfg.ini is read in order to configure
367 the desired trace levels.
368
369 \param - moduleId - module whose trace level is being configured
370 \param - bitmask - bitmask of log levels to be enabled
371
372 \return - void
373
374 --------------------------------------------------------------------------*/
375static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
376{
377 wpt_tracelevel level;
378
379 /* if the bitmask is the default value, then a bitmask was not
380 specified in cfg.ini, so leave the logging level alone (it
381 will remain at the "compiled in" default value) */
382 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
383 {
384 return;
385 }
386
387 /* a mask was specified. start by disabling all logging */
388 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
389
390 /* now cycle through the bitmask until all "set" bits are serviced */
391 level = VOS_TRACE_LEVEL_FATAL;
392 while (0 != bitmask)
393 {
394 if (bitmask & 1)
395 {
396 vos_trace_setValue(moduleId, level, 1);
397 }
398 level++;
399 bitmask >>= 1;
400 }
401}
402
403
Jeff Johnson295189b2012-06-20 16:38:30 -0700404/**---------------------------------------------------------------------------
405
406 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
407
408 Called immediately after the cfg.ini is read in order to configure
409 the desired trace levels in the WDI.
410
411 \param - moduleId - module whose trace level is being configured
412 \param - bitmask - bitmask of log levels to be enabled
413
414 \return - void
415
416 --------------------------------------------------------------------------*/
417static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
418{
419 wpt_tracelevel level;
420
421 /* if the bitmask is the default value, then a bitmask was not
422 specified in cfg.ini, so leave the logging level alone (it
423 will remain at the "compiled in" default value) */
424 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
425 {
426 return;
427 }
428
429 /* a mask was specified. start by disabling all logging */
430 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
431
432 /* now cycle through the bitmask until all "set" bits are serviced */
433 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
434 while (0 != bitmask)
435 {
436 if (bitmask & 1)
437 {
438 wpalTraceSetLevel(moduleId, level, 1);
439 }
440 level++;
441 bitmask >>= 1;
442 }
443}
Jeff Johnson295189b2012-06-20 16:38:30 -0700444
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530445/*
446 * FUNCTION: wlan_hdd_validate_context
447 * This function is used to check the HDD context
448 */
449int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
450{
451 ENTER();
452
453 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
454 {
455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
456 "%s: HDD context is Null", __func__);
457 return -ENODEV;
458 }
459
460 if (pHddCtx->isLogpInProgress)
461 {
462 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
463 "%s: LOGP in Progress. Ignore!!!", __func__);
464 return -EAGAIN;
465 }
466
467 if (pHddCtx->isLoadUnloadInProgress)
468 {
469 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
470 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
471 return -EAGAIN;
472 }
473 return 0;
474}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700475#ifdef CONFIG_ENABLE_LINUX_REG
476void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
477{
478 hdd_adapter_t *pAdapter = NULL;
479 hdd_station_ctx_t *pHddStaCtx = NULL;
480 eCsrPhyMode phyMode;
481 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530482
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700483 if (NULL == pHddCtx)
484 {
485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
486 "HDD Context is null !!");
487 return ;
488 }
489
490 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
491 if (NULL == pAdapter)
492 {
493 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
494 "pAdapter is null !!");
495 return ;
496 }
497
498 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
499 if (NULL == pHddStaCtx)
500 {
501 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
502 "pHddStaCtx is null !!");
503 return ;
504 }
505
506 cfg_param = pHddCtx->cfg_ini;
507 if (NULL == cfg_param)
508 {
509 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
510 "cfg_params not available !!");
511 return ;
512 }
513
514 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
515
516 if (!pHddCtx->isVHT80Allowed)
517 {
518 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
519 (eCSR_DOT11_MODE_11ac == phyMode) ||
520 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
521 {
522 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
523 "Setting phymode to 11n!!");
524 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
525 }
526 }
527 else
528 {
529 /*New country Supports 11ac as well resetting value back from .ini*/
530 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
531 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
532 return ;
533 }
534
535 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
536 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
537 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
538 {
539 VOS_STATUS vosStatus;
540
541 // need to issue a disconnect to CSR.
542 INIT_COMPLETION(pAdapter->disconnect_comp_var);
543 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
544 pAdapter->sessionId,
545 eCSR_DISCONNECT_REASON_UNSPECIFIED );
546
547 if (VOS_STATUS_SUCCESS == vosStatus)
548 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
549 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
550
551 }
552}
553#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530554void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
555{
556 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
557 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
558 hdd_config_t *cfg_param;
559 eCsrPhyMode phyMode;
560
561 if (NULL == pHddCtx)
562 {
563 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
564 "HDD Context is null !!");
565 return ;
566 }
567
568 cfg_param = pHddCtx->cfg_ini;
569
570 if (NULL == cfg_param)
571 {
572 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
573 "cfg_params not available !!");
574 return ;
575 }
576
577 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
578
579 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
580 {
581 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
582 (eCSR_DOT11_MODE_11ac == phyMode) ||
583 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
584 {
585 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
586 "Setting phymode to 11n!!");
587 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
588 }
589 }
590 else
591 {
592 /*New country Supports 11ac as well resetting value back from .ini*/
593 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
594 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
595 return ;
596 }
597
598 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
599 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
600 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
601 {
602 VOS_STATUS vosStatus;
603
604 // need to issue a disconnect to CSR.
605 INIT_COMPLETION(pAdapter->disconnect_comp_var);
606 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
607 pAdapter->sessionId,
608 eCSR_DISCONNECT_REASON_UNSPECIFIED );
609
610 if (VOS_STATUS_SUCCESS == vosStatus)
611 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
612 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
613
614 }
615}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700616#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530617
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700618void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
619{
620 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
621 hdd_config_t *cfg_param;
622
623 if (NULL == pHddCtx)
624 {
625 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
626 "HDD Context is null !!");
627 return ;
628 }
629
630 cfg_param = pHddCtx->cfg_ini;
631
632 if (NULL == cfg_param)
633 {
634 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
635 "cfg_params not available !!");
636 return ;
637 }
638
639 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
640 {
641 /*New country doesn't support DFS */
642 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
643 }
644 else
645 {
646 /*New country Supports DFS as well resetting value back from .ini*/
647 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
648 }
649
650}
651
Rajeev79dbe4c2013-10-05 11:03:42 +0530652#ifdef FEATURE_WLAN_BATCH_SCAN
653
654/**---------------------------------------------------------------------------
655
656 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
657 input string
658
659 This function extracts assigned integer from string in below format:
660 "STRING=10" : extracts integer 10 from this string
661
662 \param - pInPtr Pointer to input string
663 \param - base Base for string to int conversion(10 for decimal 16 for hex)
664 \param - pOutPtr Pointer to variable in which extracted integer needs to be
665 assigned
666 \param - pLastArg to tell whether it is last arguement in input string or
667 not
668
669 \return - NULL for failure cases
670 pointer to next arguement in input string for success cases
671 --------------------------------------------------------------------------*/
672static tANI_U8 *
673hdd_extract_assigned_int_from_str
674(
675 tANI_U8 *pInPtr,
676 tANI_U8 base,
677 tANI_U32 *pOutPtr,
678 tANI_U8 *pLastArg
679)
680{
681 int tempInt;
682 int v = 0;
683 char buf[32];
684 int val = 0;
685 *pLastArg = FALSE;
686
687 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
688 if (NULL == pInPtr)
689 {
690 return NULL;
691 }
692
693 pInPtr++;
694
695 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
696
697 val = sscanf(pInPtr, "%32s ", buf);
698 if (val < 0 && val > strlen(pInPtr))
699 {
700 return NULL;
701 }
702 pInPtr += val;
703 v = kstrtos32(buf, base, &tempInt);
704 if (v < 0)
705 {
706 return NULL;
707 }
708 *pOutPtr = tempInt;
709
710 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
711 if (NULL == pInPtr)
712 {
713 *pLastArg = TRUE;
714 return NULL;
715 }
716 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
717
718 return pInPtr;
719}
720
721/**---------------------------------------------------------------------------
722
723 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
724 input string
725
726 This function extracts assigned character from string in below format:
727 "STRING=A" : extracts char 'A' from this string
728
729 \param - pInPtr Pointer to input string
730 \param - pOutPtr Pointer to variable in which extracted char needs to be
731 assigned
732 \param - pLastArg to tell whether it is last arguement in input string or
733 not
734
735 \return - NULL for failure cases
736 pointer to next arguement in input string for success cases
737 --------------------------------------------------------------------------*/
738static tANI_U8 *
739hdd_extract_assigned_char_from_str
740(
741 tANI_U8 *pInPtr,
742 tANI_U8 *pOutPtr,
743 tANI_U8 *pLastArg
744)
745{
746 *pLastArg = FALSE;
747
748 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
749 if (NULL == pInPtr)
750 {
751 return NULL;
752 }
753
754 pInPtr++;
755
756 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
757
758 *pOutPtr = *pInPtr;
759
760 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
761 if (NULL == pInPtr)
762 {
763 *pLastArg = TRUE;
764 return NULL;
765 }
766 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
767
768 return pInPtr;
769}
770
771
772/**---------------------------------------------------------------------------
773
774 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
775
776 This function parses set batch scan command in below format:
777 WLS_BATCHING_SET <space> followed by below arguements
778 "SCANFREQ=XX" : Optional defaults to 30 sec
779 "MSCAN=XX" : Required number of scans to attempt to batch
780 "BESTN=XX" : Best Network (RSSI) defaults to 16
781 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
782 A. implies only 5 GHz , B. implies only 2.4GHz
783 "RTT=X" : optional defaults to 0
784 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
785 error
786
787 For example input commands:
788 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
789 translated into set batch scan with following parameters:
790 a) Frequence 60 seconds
791 b) Batch 10 scans together
792 c) Best RSSI to be 20
793 d) 5GHz band only
794 e) RTT is equal to 0
795
796 \param - pValue Pointer to input channel list
797 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
798
799 \return - 0 for success non-zero for failure
800
801 --------------------------------------------------------------------------*/
802static int
803hdd_parse_set_batchscan_command
804(
805 tANI_U8 *pValue,
806 tSirSetBatchScanReq *pHddSetBatchScanReq
807)
808{
809 tANI_U8 *inPtr = pValue;
810 tANI_U8 val = 0;
811 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800812 tANI_U32 nScanFreq;
813 tANI_U32 nMscan;
814 tANI_U32 nBestN;
815 tANI_U8 ucRfBand;
816 tANI_U32 nRtt;
Rajeev79dbe4c2013-10-05 11:03:42 +0530817
818 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800819 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
820 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
821 nRtt = 0;
822 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530823
824 /*go to space after WLS_BATCHING_SET command*/
825 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
826 /*no argument after the command*/
827 if (NULL == inPtr)
828 {
829 return -EINVAL;
830 }
831
832 /*no space after the command*/
833 else if (SPACE_ASCII_VALUE != *inPtr)
834 {
835 return -EINVAL;
836 }
837
838 /*removing empty spaces*/
839 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
840
841 /*no argument followed by spaces*/
842 if ('\0' == *inPtr)
843 {
844 return -EINVAL;
845 }
846
847 /*check and parse SCANFREQ*/
848 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
849 {
850 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800851 &nScanFreq, &lastArg);
852
853 if (0 == nScanFreq)
854 {
855 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
856 }
857
Rajeev79dbe4c2013-10-05 11:03:42 +0530858 if ( (NULL == inPtr) || (TRUE == lastArg))
859 {
860 return -EINVAL;
861 }
862 }
863
864 /*check and parse MSCAN*/
865 if ((strncmp(inPtr, "MSCAN", 5) == 0))
866 {
867 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800868 &nMscan, &lastArg);
869
870 if (0 == nMscan)
871 {
872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
873 "invalid MSCAN=%d", nMscan);
874 return -EINVAL;
875 }
876
Rajeev79dbe4c2013-10-05 11:03:42 +0530877 if (TRUE == lastArg)
878 {
879 goto done;
880 }
881 else if (NULL == inPtr)
882 {
883 return -EINVAL;
884 }
885 }
886 else
887 {
888 return -EINVAL;
889 }
890
891 /*check and parse BESTN*/
892 if ((strncmp(inPtr, "BESTN", 5) == 0))
893 {
894 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800895 &nBestN, &lastArg);
896
897 if (0 == nBestN)
898 {
899 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
900 }
901
Rajeev79dbe4c2013-10-05 11:03:42 +0530902 if (TRUE == lastArg)
903 {
904 goto done;
905 }
906 else if (NULL == inPtr)
907 {
908 return -EINVAL;
909 }
910 }
911
912 /*check and parse CHANNEL*/
913 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
914 {
915 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
916 if (TRUE == lastArg)
917 {
918 goto done;
919 }
920 else if (NULL == inPtr)
921 {
922 return -EINVAL;
923 }
924 if (('A' == val) || ('a' == val))
925 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800926 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530927 }
928 else if (('B' == val) || ('b' == val))
929 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800930 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530931 }
932 else
933 {
934 return -EINVAL;
935 }
936 }
937
938 /*check and parse RTT*/
939 if ((strncmp(inPtr, "RTT", 3) == 0))
940 {
941 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800942 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530943 if (TRUE == lastArg)
944 {
945 goto done;
946 }
947 if (NULL == inPtr)
948 {
949 return -EINVAL;
950 }
951 }
952
953
954done:
955
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800956 pHddSetBatchScanReq->scanFrequency = nScanFreq;
957 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
958 pHddSetBatchScanReq->bestNetwork = nBestN;
959 pHddSetBatchScanReq->rfBand = ucRfBand;
960 pHddSetBatchScanReq->rtt = nRtt;
961
Rajeev79dbe4c2013-10-05 11:03:42 +0530962 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
963 "Received WLS_BATCHING_SET with SCANFREQ=%d "
964 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
965 pHddSetBatchScanReq->scanFrequency,
966 pHddSetBatchScanReq->numberOfScansToBatch,
967 pHddSetBatchScanReq->bestNetwork,
968 pHddSetBatchScanReq->rfBand,
969 pHddSetBatchScanReq->rtt);
970
971 return 0;
972}/*End of hdd_parse_set_batchscan_command*/
973
974/**---------------------------------------------------------------------------
975
976 \brief hdd_set_batch_scan_req_callback () - This function is called after
977 receiving set batch scan response from FW and it saves set batch scan
978 response data FW to HDD context and sets the completion event on
979 which hdd_ioctl is waiting
980
981 \param - callbackContext Pointer to HDD adapter
982 \param - pRsp Pointer to set batch scan response data received from FW
983
984 \return - nothing
985
986 --------------------------------------------------------------------------*/
987static void hdd_set_batch_scan_req_callback
988(
989 void *callbackContext,
990 tSirSetBatchScanRsp *pRsp
991)
992{
993 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
994 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
995
996 /*sanity check*/
997 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
998 {
999 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1000 "%s: Invalid pAdapter magic", __func__);
1001 VOS_ASSERT(0);
1002 return;
1003 }
1004 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1005
1006 /*save set batch scan response*/
1007 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1008
1009 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1010 "Received set batch scan rsp from FW with nScansToBatch=%d",
1011 pHddSetBatchScanRsp->nScansToBatch);
1012
1013 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1014 complete(&pAdapter->hdd_set_batch_scan_req_var);
1015
1016 return;
1017}/*End of hdd_set_batch_scan_req_callback*/
1018
1019
1020/**---------------------------------------------------------------------------
1021
1022 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1023 info in hdd batch scan response queue
1024
1025 \param - pAdapter Pointer to hdd adapter
1026 \param - pAPMetaInfo Pointer to access point meta info
1027 \param - scanId scan ID of batch scan response
1028 \param - isLastAp tells whether AP is last AP in batch scan response or not
1029
1030 \return - nothing
1031
1032 --------------------------------------------------------------------------*/
1033static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1034 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1035{
1036 tHddBatchScanRsp *pHead;
1037 tHddBatchScanRsp *pNode;
1038 tHddBatchScanRsp *pPrev;
1039 tHddBatchScanRsp *pTemp;
1040 tANI_U8 ssidLen;
1041
1042 /*head of hdd batch scan response queue*/
1043 pHead = pAdapter->pBatchScanRsp;
1044
1045 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1046 if (NULL == pNode)
1047 {
1048 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1049 "%s: Could not allocate memory", __func__);
1050 VOS_ASSERT(0);
1051 return;
1052 }
1053
1054 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1055 sizeof(pNode->ApInfo.bssid));
1056 ssidLen = strlen(pApMetaInfo->ssid);
1057 if (SIR_MAX_SSID_SIZE < ssidLen)
1058 {
1059 /*invalid scan result*/
1060 vos_mem_free(pNode);
1061 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1062 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1063 return;
1064 }
1065 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1066 /*null terminate ssid*/
1067 pNode->ApInfo.ssid[ssidLen] = '\0';
1068 pNode->ApInfo.ch = pApMetaInfo->ch;
1069 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1070 pNode->ApInfo.age = pApMetaInfo->timestamp;
1071 pNode->ApInfo.batchId = scanId;
1072 pNode->ApInfo.isLastAp = isLastAp;
1073
1074 pNode->pNext = NULL;
1075 if (NULL == pHead)
1076 {
1077 pAdapter->pBatchScanRsp = pNode;
1078 }
1079 else
1080 {
1081 pTemp = pHead;
1082 while (NULL != pTemp)
1083 {
1084 pPrev = pTemp;
1085 pTemp = pTemp->pNext;
1086 }
1087 pPrev->pNext = pNode;
1088 }
1089
1090 return;
1091}/*End of hdd_populate_batch_scan_rsp_queue*/
1092
1093/**---------------------------------------------------------------------------
1094
1095 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1096 receiving batch scan response indication from FW. It saves get batch scan
1097 response data in HDD batch scan response queue. This callback sets the
1098 completion event on which hdd_ioctl is waiting only after getting complete
1099 batch scan response data from FW
1100
1101 \param - callbackContext Pointer to HDD adapter
1102 \param - pRsp Pointer to get batch scan response data received from FW
1103
1104 \return - nothing
1105
1106 --------------------------------------------------------------------------*/
1107static void hdd_batch_scan_result_ind_callback
1108(
1109 void *callbackContext,
1110 void *pRsp
1111)
1112{
1113 v_BOOL_t isLastAp;
1114 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001115 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301116 tANI_U32 numberScanList;
1117 tANI_U32 nextScanListOffset;
1118 tANI_U32 nextApMetaInfoOffset;
1119 hdd_adapter_t* pAdapter;
1120 tpSirBatchScanList pScanList;
1121 tpSirBatchScanNetworkInfo pApMetaInfo;
1122 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1123 tSirSetBatchScanReq *pReq;
1124
1125 pAdapter = (hdd_adapter_t *)callbackContext;
1126 /*sanity check*/
1127 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1128 {
1129 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1130 "%s: Invalid pAdapter magic", __func__);
1131 VOS_ASSERT(0);
1132 return;
1133 }
1134
1135 /*initialize locals*/
1136 pReq = &pAdapter->hddSetBatchScanReq;
1137 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1138 isLastAp = FALSE;
1139 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001140 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301141 numberScanList = 0;
1142 nextScanListOffset = 0;
1143 nextApMetaInfoOffset = 0;
1144 pScanList = NULL;
1145 pApMetaInfo = NULL;
1146
1147 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1148 {
1149 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1150 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1151 isLastAp = TRUE;
1152 goto done;
1153 }
1154
1155 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1156 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1157 "Batch scan rsp: numberScalList %d", numberScanList);
1158
1159 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1160 {
1161 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1162 "%s: numberScanList %d", __func__, numberScanList);
1163 isLastAp = TRUE;
1164 goto done;
1165 }
1166
1167 while (numberScanList)
1168 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001169 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301170 nextScanListOffset);
1171 if (NULL == pScanList)
1172 {
1173 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1174 "%s: pScanList is %p", __func__, pScanList);
1175 isLastAp = TRUE;
1176 goto done;
1177 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001178 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301179 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001180 "Batch scan rsp: numApMetaInfo %d scanId %d",
1181 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301182
1183 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1184 {
1185 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1186 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1187 isLastAp = TRUE;
1188 goto done;
1189 }
1190
Rajeev Kumarce651e42013-10-21 18:57:15 -07001191 /*Initialize next AP meta info offset for next scan list*/
1192 nextApMetaInfoOffset = 0;
1193
Rajeev79dbe4c2013-10-05 11:03:42 +05301194 while (numApMetaInfo)
1195 {
1196 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1197 nextApMetaInfoOffset);
1198 if (NULL == pApMetaInfo)
1199 {
1200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1201 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1202 isLastAp = TRUE;
1203 goto done;
1204 }
1205 /*calculate AP age*/
1206 pApMetaInfo->timestamp =
1207 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1208
1209 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001210 "%s: bssId "MAC_ADDRESS_STR
1211 " ch %d rssi %d timestamp %d", __func__,
1212 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1213 pApMetaInfo->ch, pApMetaInfo->rssi,
1214 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301215
1216 /*mark last AP in batch scan response*/
1217 if ((TRUE == pBatchScanRsp->isLastResult) &&
1218 (1 == numberScanList) && (1 == numApMetaInfo))
1219 {
1220 isLastAp = TRUE;
1221 }
1222
1223 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1224 /*store batch scan repsonse in hdd queue*/
1225 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1226 pScanList->scanId, isLastAp);
1227 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1228
1229 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1230 numApMetaInfo--;
1231 }
1232
Rajeev Kumarce651e42013-10-21 18:57:15 -07001233 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1234 + (sizeof(tSirBatchScanNetworkInfo)
1235 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301236 numberScanList--;
1237 }
1238
1239done:
1240
1241 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1242 requested from hdd_ioctl*/
1243 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1244 (TRUE == isLastAp))
1245 {
1246 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1247 complete(&pAdapter->hdd_get_batch_scan_req_var);
1248 }
1249
1250 return;
1251}/*End of hdd_batch_scan_result_ind_callback*/
1252
1253/**---------------------------------------------------------------------------
1254
1255 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1256 response as per batch scan FR request format by putting proper markers
1257
1258 \param - pDest pointer to destination buffer
1259 \param - cur_len current length
1260 \param - tot_len total remaining size which can be written to user space
1261 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1262 \param - pAdapter Pointer to HDD adapter
1263
1264 \return - ret no of characters written
1265
1266 --------------------------------------------------------------------------*/
1267static tANI_U32
1268hdd_format_batch_scan_rsp
1269(
1270 tANI_U8 *pDest,
1271 tANI_U32 cur_len,
1272 tANI_U32 tot_len,
1273 tHddBatchScanRsp *pApMetaInfo,
1274 hdd_adapter_t* pAdapter
1275)
1276{
1277 tANI_U32 ret = 0;
1278 tANI_U32 rem_len = 0;
1279 tANI_U8 temp_len = 0;
1280 tANI_U8 temp_total_len = 0;
1281 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1282 tANI_U8 *pTemp = temp;
1283
1284 /*Batch scan reponse needs to be returned to user space in
1285 following format:
1286 "scancount=X\n" where X is the number of scans in current batch
1287 batch
1288 "trunc\n" optional present if current scan truncated
1289 "bssid=XX:XX:XX:XX:XX:XX\n"
1290 "ssid=XXXX\n"
1291 "freq=X\n" frequency in Mhz
1292 "level=XX\n"
1293 "age=X\n" ms
1294 "dist=X\n" cm (-1 if not available)
1295 "errror=X\n" (-1if not available)
1296 "====\n" (end of ap marker)
1297 "####\n" (end of scan marker)
1298 "----\n" (end of results)*/
1299 /*send scan result in above format to user space based on
1300 available length*/
1301 /*The GET response may have more data than the driver can return in its
1302 buffer. In that case the buffer should be filled to the nearest complete
1303 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1304 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1305 The final buffer should end with "----\n"*/
1306
1307 /*sanity*/
1308 if (cur_len > tot_len)
1309 {
1310 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1311 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1312 return 0;
1313 }
1314 else
1315 {
1316 rem_len = (tot_len - cur_len);
1317 }
1318
1319 /*end scan marker*/
1320 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1321 {
1322 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1323 pTemp += temp_len;
1324 temp_total_len += temp_len;
1325 }
1326
1327 /*bssid*/
1328 temp_len = snprintf(pTemp, sizeof(temp),
1329 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1330 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1331 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1332 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1333 pTemp += temp_len;
1334 temp_total_len += temp_len;
1335
1336 /*ssid*/
1337 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1338 pApMetaInfo->ApInfo.ssid);
1339 pTemp += temp_len;
1340 temp_total_len += temp_len;
1341
1342 /*freq*/
1343 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001344 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301345 pTemp += temp_len;
1346 temp_total_len += temp_len;
1347
1348 /*level*/
1349 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1350 pApMetaInfo->ApInfo.rssi);
1351 pTemp += temp_len;
1352 temp_total_len += temp_len;
1353
1354 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001355 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301356 pApMetaInfo->ApInfo.age);
1357 pTemp += temp_len;
1358 temp_total_len += temp_len;
1359
1360 /*dist*/
1361 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1362 pTemp += temp_len;
1363 temp_total_len += temp_len;
1364
1365 /*error*/
1366 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1367 pTemp += temp_len;
1368 temp_total_len += temp_len;
1369
1370 /*end AP marker*/
1371 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1372 pTemp += temp_len;
1373 temp_total_len += temp_len;
1374
1375 /*last AP in batch scan response*/
1376 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1377 {
1378 /*end scan marker*/
1379 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1380 pTemp += temp_len;
1381 temp_total_len += temp_len;
1382
1383 /*end batch scan result marker*/
1384 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1385 pTemp += temp_len;
1386 temp_total_len += temp_len;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08001387
1388 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301389 }
1390
1391 if (temp_total_len < rem_len)
1392 {
1393 ret = temp_total_len + 1;
1394 strlcpy(pDest, temp, ret);
1395 pAdapter->isTruncated = FALSE;
1396 }
1397 else
1398 {
1399 pAdapter->isTruncated = TRUE;
1400 if (rem_len >= strlen("%%%%"))
1401 {
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08001402 ret = snprintf(pDest, strlen("%%%%"), "%%%%%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301403 }
1404 {
1405 ret = 0;
1406 }
1407 }
1408
1409 return ret;
1410
1411}/*End of hdd_format_batch_scan_rsp*/
1412
1413/**---------------------------------------------------------------------------
1414
1415 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1416 buffer starting with head of hdd batch scan response queue
1417
1418 \param - pAdapter Pointer to HDD adapter
1419 \param - pDest Pointer to user data buffer
1420 \param - cur_len current offset in user buffer
1421 \param - rem_len remaining no of bytes in user buffer
1422
1423 \return - number of bytes written in user buffer
1424
1425 --------------------------------------------------------------------------*/
1426
1427tANI_U32 hdd_populate_user_batch_scan_rsp
1428(
1429 hdd_adapter_t* pAdapter,
1430 tANI_U8 *pDest,
1431 tANI_U32 cur_len,
1432 tANI_U32 rem_len
1433)
1434{
1435 tHddBatchScanRsp *pHead;
1436 tHddBatchScanRsp *pPrev;
1437 tANI_U32 len;
1438
Rajeev79dbe4c2013-10-05 11:03:42 +05301439 pAdapter->isTruncated = FALSE;
1440
1441 /*head of hdd batch scan response queue*/
1442 pHead = pAdapter->pBatchScanRsp;
1443 while (pHead)
1444 {
1445 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1446 pAdapter);
1447 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001448 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301449 cur_len += len;
1450 if(TRUE == pAdapter->isTruncated)
1451 {
1452 /*result is truncated return rest of scan rsp in next req*/
1453 cur_len = rem_len;
1454 break;
1455 }
1456 pPrev = pHead;
1457 pHead = pHead->pNext;
1458 pAdapter->pBatchScanRsp = pHead;
1459 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1460 vos_mem_free(pPrev);
1461 }
1462
1463 return cur_len;
1464}/*End of hdd_populate_user_batch_scan_rsp*/
1465
1466/**---------------------------------------------------------------------------
1467
1468 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1469 scan response data from HDD queue to user space
1470 It does following in detail:
1471 a) if HDD has enough data in its queue then it 1st copies data to user
1472 space and then send get batch scan indication message to FW. In this
1473 case it does not wait on any event and batch scan response data will
1474 be populated in HDD response queue in MC thread context after receiving
1475 indication from FW
1476 b) else send get batch scan indication message to FW and wait on an event
1477 which will be set once HDD receives complete batch scan response from
1478 FW and then this function returns batch scan response to user space
1479
1480 \param - pAdapter Pointer to HDD adapter
1481 \param - pPrivData Pointer to priv_data
1482
1483 \return - 0 for success -EFAULT for failure
1484
1485 --------------------------------------------------------------------------*/
1486
1487int hdd_return_batch_scan_rsp_to_user
1488(
1489 hdd_adapter_t* pAdapter,
1490 hdd_priv_data_t *pPrivData,
1491 tANI_U8 *command
1492)
1493{
1494 tANI_U8 *pDest;
1495 tANI_U32 count = 0;
1496 tANI_U32 len = 0;
1497 tANI_U32 cur_len = 0;
1498 tANI_U32 rem_len = 0;
1499 eHalStatus halStatus;
1500 unsigned long rc;
1501 tSirTriggerBatchScanResultInd *pReq;
1502
1503 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1504 pReq->param = 0;/*batch scan client*/
1505 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1506 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1507
1508 cur_len = pPrivData->used_len;
1509 if (pPrivData->total_len > pPrivData->used_len)
1510 {
1511 rem_len = pPrivData->total_len - pPrivData->used_len;
1512 }
1513 else
1514 {
1515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1516 "%s: Invalid user data buffer total_len %d used_len %d",
1517 __func__, pPrivData->total_len, pPrivData->used_len);
1518 return -EFAULT;
1519 }
1520
1521 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1522 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1523 cur_len, rem_len);
1524 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1525
1526 /*enough scan result available in cache to return to user space or
1527 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001528 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301529 {
1530 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1531 halStatus = sme_TriggerBatchScanResultInd(
1532 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1533 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1534 pAdapter);
1535 if ( eHAL_STATUS_SUCCESS == halStatus )
1536 {
1537 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1538 {
1539 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1540 rc = wait_for_completion_timeout(
1541 &pAdapter->hdd_get_batch_scan_req_var,
1542 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1543 if (0 == rc)
1544 {
1545 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1546 "%s: Timeout waiting to fetch batch scan rsp from fw",
1547 __func__);
1548 return -EFAULT;
1549 }
1550 }
1551
1552 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001553 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301554 pDest += len;
1555 cur_len += len;
1556
1557 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1558 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1559 cur_len, rem_len);
1560 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1561
1562 count = 0;
1563 len = (len - pPrivData->used_len);
1564 pDest = (command + pPrivData->used_len);
1565 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001566 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301567 while(count < len)
1568 {
1569 printk("%c", *(pDest + count));
1570 count++;
1571 }
1572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1573 "%s: copy %d data to user buffer", __func__, len);
1574 if (copy_to_user(pPrivData->buf, pDest, len))
1575 {
1576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1577 "%s: failed to copy data to user buffer", __func__);
1578 return -EFAULT;
1579 }
1580 }
1581 else
1582 {
1583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1584 "sme_GetBatchScanScan returned failure halStatus %d",
1585 halStatus);
1586 return -EINVAL;
1587 }
1588 }
1589 else
1590 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301591 count = 0;
1592 len = (len - pPrivData->used_len);
1593 pDest = (command + pPrivData->used_len);
1594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001595 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301596 while(count < len)
1597 {
1598 printk("%c", *(pDest + count));
1599 count++;
1600 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001601 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1602 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301603 if (copy_to_user(pPrivData->buf, pDest, len))
1604 {
1605 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1606 "%s: failed to copy data to user buffer", __func__);
1607 return -EFAULT;
1608 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301609 }
1610
1611 return 0;
1612} /*End of hdd_return_batch_scan_rsp_to_user*/
1613
1614#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1615
Jeff Johnson295189b2012-06-20 16:38:30 -07001616int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1617{
1618 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1619 hdd_priv_data_t priv_data;
1620 tANI_U8 *command = NULL;
1621 int ret = 0;
1622
1623 if (NULL == pAdapter)
1624 {
1625 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001626 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001627 ret = -ENODEV;
1628 goto exit;
1629 }
1630
Jeff Johnsone7245742012-09-05 17:12:55 -07001631 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001632 {
1633 ret = -EINVAL;
1634 goto exit;
1635 }
1636
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001637 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1638 {
1639 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1640 "%s:LOGP in Progress. Ignore!!!", __func__);
1641 ret = -EBUSY;
1642 goto exit;
1643 }
1644
Jeff Johnson295189b2012-06-20 16:38:30 -07001645 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1646 {
1647 ret = -EFAULT;
1648 goto exit;
1649 }
1650
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001651 if (priv_data.total_len <= 0)
1652 {
1653 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1654 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1655 priv_data.total_len);
1656 ret = -EINVAL;
1657 goto exit;
1658 }
1659
1660 /* Allocate +1 for '\0' */
1661 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001662 if (!command)
1663 {
1664 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001665 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001666 ret = -ENOMEM;
1667 goto exit;
1668 }
1669
1670 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1671 {
1672 ret = -EFAULT;
1673 goto exit;
1674 }
1675
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001676 /* Making sure the command is NUL-terminated */
1677 command[priv_data.total_len] = '\0';
1678
Jeff Johnson295189b2012-06-20 16:38:30 -07001679 if ((SIOCDEVPRIVATE + 1) == cmd)
1680 {
1681 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1682
1683 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001684 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001685
1686 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1687 {
1688 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1689 sizeof(tSirMacAddr)))
1690 {
1691 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001692 "%s: failed to copy data to user buffer\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001693 ret = -EFAULT;
1694 }
1695 }
Amar Singhal0974e402013-02-12 14:27:46 -08001696 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001697 {
Amar Singhal0974e402013-02-12 14:27:46 -08001698 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001699 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001700
Jeff Johnson295189b2012-06-20 16:38:30 -07001701 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001702
1703 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001705 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001706 "%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 -07001707 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001708 ret = hdd_setBand_helper(dev, ptr);
1709 }
Kiet Lamf040f472013-11-20 21:15:23 +05301710 else if(strncmp(command, "SETWMMPS", 8) == 0)
1711 {
1712 tANI_U8 *ptr = command;
1713 ret = hdd_wmmps_helper(pAdapter, ptr);
1714 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001715 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1716 {
1717 char *country_code;
1718
1719 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001720
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001721 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001722 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001723#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301724 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001725#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001726 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1727 (void *)(tSmeChangeCountryCallback)
1728 wlan_hdd_change_country_code_callback,
1729 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE);
1730 if (eHAL_STATUS_SUCCESS == ret)
1731 {
1732 ret = wait_for_completion_interruptible_timeout(
1733 &pAdapter->change_country_code,
1734 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1735 if (0 >= ret)
1736 {
1737 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1738 __func__);
1739 }
1740 }
1741 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001742 {
1743 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001744 "%s: SME Change Country code fail ret=%d", __func__, ret);
1745 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001746 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001747
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001748 }
1749 /*
1750 command should be a string having format
1751 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1752 */
Amar Singhal0974e402013-02-12 14:27:46 -08001753 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001754 {
Amar Singhal0974e402013-02-12 14:27:46 -08001755 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001756
1757 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001758 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001759
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001760 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001761 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001762 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1763 {
1764 int suspend = 0;
1765 tANI_U8 *ptr = (tANI_U8*)command + 15;
1766
1767 suspend = *ptr - '0';
1768 hdd_set_wlan_suspend_mode(suspend);
1769 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001770#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1771 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1772 {
1773 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001774 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001775 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1776 eHalStatus status = eHAL_STATUS_SUCCESS;
1777
1778 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1779 value = value + 15;
1780
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001781 /* Convert the value from ascii to integer */
1782 ret = kstrtos8(value, 10, &rssi);
1783 if (ret < 0)
1784 {
1785 /* If the input value is greater than max value of datatype, then also
1786 kstrtou8 fails */
1787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1788 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001789 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001790 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1791 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1792 ret = -EINVAL;
1793 goto exit;
1794 }
1795
Srinivas Girigowdade697412013-02-14 16:31:48 -08001796 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001797
Srinivas Girigowdade697412013-02-14 16:31:48 -08001798 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1799 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1800 {
1801 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1802 "Neighbor lookup threshold value %d is out of range"
1803 " (Min: %d Max: %d)", lookUpThreshold,
1804 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1805 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1806 ret = -EINVAL;
1807 goto exit;
1808 }
1809
1810 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1811 "%s: Received Command to Set Roam trigger"
1812 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1813
1814 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1815 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1816 if (eHAL_STATUS_SUCCESS != status)
1817 {
1818 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1819 "%s: Failed to set roam trigger, try again", __func__);
1820 ret = -EPERM;
1821 goto exit;
1822 }
1823
1824 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1825 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1826 }
1827 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1828 {
1829 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1830 int rssi = (-1) * lookUpThreshold;
1831 char extra[32];
1832 tANI_U8 len = 0;
1833
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001834 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001835 if (copy_to_user(priv_data.buf, &extra, len + 1))
1836 {
1837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1838 "%s: failed to copy data to user buffer", __func__);
1839 ret = -EFAULT;
1840 goto exit;
1841 }
1842 }
1843 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1844 {
1845 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001846 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001847 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001848
Srinivas Girigowdade697412013-02-14 16:31:48 -08001849 /* input refresh period is in terms of seconds */
1850 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1851 value = value + 18;
1852 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001853 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001854 if (ret < 0)
1855 {
1856 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001857 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001858 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001859 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001860 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001861 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1862 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001863 ret = -EINVAL;
1864 goto exit;
1865 }
1866
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001867 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1868 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001869 {
1870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001871 "Roam scan period value %d is out of range"
1872 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001873 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1874 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001875 ret = -EINVAL;
1876 goto exit;
1877 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001878 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001879
1880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1881 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001882 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001883
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001884 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1885 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001886 }
1887 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1888 {
1889 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1890 char extra[32];
1891 tANI_U8 len = 0;
1892
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001893 len = scnprintf(extra, sizeof(extra), "%s %d",
1894 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001895 /* Returned value is in units of seconds */
1896 if (copy_to_user(priv_data.buf, &extra, len + 1))
1897 {
1898 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1899 "%s: failed to copy data to user buffer", __func__);
1900 ret = -EFAULT;
1901 goto exit;
1902 }
1903 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001904 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1905 {
1906 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001907 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001908 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001909
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001910 /* input refresh period is in terms of seconds */
1911 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1912 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001913
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001914 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001915 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001916 if (ret < 0)
1917 {
1918 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001919 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001920 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001921 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001922 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001923 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1924 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1925 ret = -EINVAL;
1926 goto exit;
1927 }
1928
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001929 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1930 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1931 {
1932 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1933 "Neighbor scan results refresh period value %d is out of range"
1934 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1935 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1936 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1937 ret = -EINVAL;
1938 goto exit;
1939 }
1940 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1941
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001942 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1943 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001944 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001945
1946 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1947 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1948 }
1949 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1950 {
1951 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1952 char extra[32];
1953 tANI_U8 len = 0;
1954
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001955 len = scnprintf(extra, sizeof(extra), "%s %d",
1956 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001957 /* Returned value is in units of seconds */
1958 if (copy_to_user(priv_data.buf, &extra, len + 1))
1959 {
1960 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1961 "%s: failed to copy data to user buffer", __func__);
1962 ret = -EFAULT;
1963 goto exit;
1964 }
1965 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001966#ifdef FEATURE_WLAN_LFR
1967 /* SETROAMMODE */
1968 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1969 {
1970 tANI_U8 *value = command;
1971 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1972
1973 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1974 value = value + SIZE_OF_SETROAMMODE + 1;
1975
1976 /* Convert the value from ascii to integer */
1977 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1978 if (ret < 0)
1979 {
1980 /* If the input value is greater than max value of datatype, then also
1981 kstrtou8 fails */
1982 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1983 "%s: kstrtou8 failed range [%d - %d]", __func__,
1984 CFG_LFR_FEATURE_ENABLED_MIN,
1985 CFG_LFR_FEATURE_ENABLED_MAX);
1986 ret = -EINVAL;
1987 goto exit;
1988 }
1989 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1990 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1991 {
1992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1993 "Roam Mode value %d is out of range"
1994 " (Min: %d Max: %d)", roamMode,
1995 CFG_LFR_FEATURE_ENABLED_MIN,
1996 CFG_LFR_FEATURE_ENABLED_MAX);
1997 ret = -EINVAL;
1998 goto exit;
1999 }
2000
2001 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2002 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2003 /*
2004 * Note that
2005 * SETROAMMODE 0 is to enable LFR while
2006 * SETROAMMODE 1 is to disable LFR, but
2007 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2008 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2009 */
2010 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2011 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2012 else
2013 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2014
2015 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2016 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2017 }
2018 /* GETROAMMODE */
2019 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2020 {
2021 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2022 char extra[32];
2023 tANI_U8 len = 0;
2024
2025 /*
2026 * roamMode value shall be inverted because the sementics is different.
2027 */
2028 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2029 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2030 else
2031 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2032
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002033 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002034 if (copy_to_user(priv_data.buf, &extra, len + 1))
2035 {
2036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2037 "%s: failed to copy data to user buffer", __func__);
2038 ret = -EFAULT;
2039 goto exit;
2040 }
2041 }
2042#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002043#endif
2044#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2045 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2046 {
2047 tANI_U8 *value = command;
2048 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2049
2050 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2051 value = value + 13;
2052 /* Convert the value from ascii to integer */
2053 ret = kstrtou8(value, 10, &roamRssiDiff);
2054 if (ret < 0)
2055 {
2056 /* If the input value is greater than max value of datatype, then also
2057 kstrtou8 fails */
2058 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2059 "%s: kstrtou8 failed range [%d - %d]", __func__,
2060 CFG_ROAM_RSSI_DIFF_MIN,
2061 CFG_ROAM_RSSI_DIFF_MAX);
2062 ret = -EINVAL;
2063 goto exit;
2064 }
2065
2066 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2067 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2068 {
2069 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2070 "Roam rssi diff value %d is out of range"
2071 " (Min: %d Max: %d)", roamRssiDiff,
2072 CFG_ROAM_RSSI_DIFF_MIN,
2073 CFG_ROAM_RSSI_DIFF_MAX);
2074 ret = -EINVAL;
2075 goto exit;
2076 }
2077
2078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2079 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2080
2081 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2082 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2083 }
2084 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2085 {
2086 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2087 char extra[32];
2088 tANI_U8 len = 0;
2089
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002090 len = scnprintf(extra, sizeof(extra), "%s %d",
2091 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002092 if (copy_to_user(priv_data.buf, &extra, len + 1))
2093 {
2094 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2095 "%s: failed to copy data to user buffer", __func__);
2096 ret = -EFAULT;
2097 goto exit;
2098 }
2099 }
2100#endif
2101#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2102 else if (strncmp(command, "GETBAND", 7) == 0)
2103 {
2104 int band = -1;
2105 char extra[32];
2106 tANI_U8 len = 0;
2107 hdd_getBand_helper(pHddCtx, &band);
2108
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002109 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002110 if (copy_to_user(priv_data.buf, &extra, len + 1))
2111 {
2112 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2113 "%s: failed to copy data to user buffer", __func__);
2114 ret = -EFAULT;
2115 goto exit;
2116 }
2117 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002118 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2119 {
2120 tANI_U8 *value = command;
2121 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2122 tANI_U8 numChannels = 0;
2123 eHalStatus status = eHAL_STATUS_SUCCESS;
2124
2125 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2126 if (eHAL_STATUS_SUCCESS != status)
2127 {
2128 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2129 "%s: Failed to parse channel list information", __func__);
2130 ret = -EINVAL;
2131 goto exit;
2132 }
2133
2134 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2135 {
2136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2137 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2138 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2139 ret = -EINVAL;
2140 goto exit;
2141 }
2142 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2143 numChannels);
2144 if (eHAL_STATUS_SUCCESS != status)
2145 {
2146 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2147 "%s: Failed to update channel list information", __func__);
2148 ret = -EINVAL;
2149 goto exit;
2150 }
2151 }
2152 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2153 {
2154 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2155 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002156 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002157 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002158 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002159
2160 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2161 ChannelList, &numChannels ))
2162 {
2163 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2164 "%s: failed to get roam scan channel list", __func__);
2165 ret = -EFAULT;
2166 goto exit;
2167 }
2168 /* output channel list is of the format
2169 [Number of roam scan channels][Channel1][Channel2]... */
2170 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002171 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002172 for (j = 0; (j < numChannels); j++)
2173 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002174 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2175 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002176 }
2177
2178 if (copy_to_user(priv_data.buf, &extra, len + 1))
2179 {
2180 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2181 "%s: failed to copy data to user buffer", __func__);
2182 ret = -EFAULT;
2183 goto exit;
2184 }
2185 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002186 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2187 {
2188 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2189 char extra[32];
2190 tANI_U8 len = 0;
2191
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002192 /* Check if the features OKC/CCX/11R are supported simultaneously,
2193 then this operation is not permitted (return FAILURE) */
2194 if (ccxMode &&
2195 hdd_is_okc_mode_enabled(pHddCtx) &&
2196 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2197 {
2198 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2199 "%s: OKC/CCX/11R are supported simultaneously"
2200 " hence this operation is not permitted!", __func__);
2201 ret = -EPERM;
2202 goto exit;
2203 }
2204
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002205 len = scnprintf(extra, sizeof(extra), "%s %d",
2206 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002207 if (copy_to_user(priv_data.buf, &extra, len + 1))
2208 {
2209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2210 "%s: failed to copy data to user buffer", __func__);
2211 ret = -EFAULT;
2212 goto exit;
2213 }
2214 }
2215 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2216 {
2217 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2218 char extra[32];
2219 tANI_U8 len = 0;
2220
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002221 /* Check if the features OKC/CCX/11R are supported simultaneously,
2222 then this operation is not permitted (return FAILURE) */
2223 if (okcMode &&
2224 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2225 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2226 {
2227 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2228 "%s: OKC/CCX/11R are supported simultaneously"
2229 " hence this operation is not permitted!", __func__);
2230 ret = -EPERM;
2231 goto exit;
2232 }
2233
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002234 len = scnprintf(extra, sizeof(extra), "%s %d",
2235 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002236 if (copy_to_user(priv_data.buf, &extra, len + 1))
2237 {
2238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2239 "%s: failed to copy data to user buffer", __func__);
2240 ret = -EFAULT;
2241 goto exit;
2242 }
2243 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002244 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002245 {
2246 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2247 char extra[32];
2248 tANI_U8 len = 0;
2249
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002250 len = scnprintf(extra, sizeof(extra), "%s %d",
2251 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002252 if (copy_to_user(priv_data.buf, &extra, len + 1))
2253 {
2254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2255 "%s: failed to copy data to user buffer", __func__);
2256 ret = -EFAULT;
2257 goto exit;
2258 }
2259 }
2260 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2261 {
2262 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2263 char extra[32];
2264 tANI_U8 len = 0;
2265
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002266 len = scnprintf(extra, sizeof(extra), "%s %d",
2267 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002268 if (copy_to_user(priv_data.buf, &extra, len + 1))
2269 {
2270 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2271 "%s: failed to copy data to user buffer", __func__);
2272 ret = -EFAULT;
2273 goto exit;
2274 }
2275 }
2276 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2277 {
2278 tANI_U8 *value = command;
2279 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2280
2281 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2282 value = value + 26;
2283 /* Convert the value from ascii to integer */
2284 ret = kstrtou8(value, 10, &minTime);
2285 if (ret < 0)
2286 {
2287 /* If the input value is greater than max value of datatype, then also
2288 kstrtou8 fails */
2289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2290 "%s: kstrtou8 failed range [%d - %d]", __func__,
2291 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2292 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2293 ret = -EINVAL;
2294 goto exit;
2295 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002296 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2297 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2298 {
2299 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2300 "scan min channel time value %d is out of range"
2301 " (Min: %d Max: %d)", minTime,
2302 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2303 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2304 ret = -EINVAL;
2305 goto exit;
2306 }
2307
2308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2309 "%s: Received Command to change channel min time = %d", __func__, minTime);
2310
2311 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2312 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2313 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002314 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2315 {
2316 tANI_U8 *value = command;
2317 tANI_U8 channel = 0;
2318 tANI_U8 dwellTime = 0;
2319 tANI_U8 bufLen = 0;
2320 tANI_U8 *buf = NULL;
2321 tSirMacAddr targetApBssid;
2322 eHalStatus status = eHAL_STATUS_SUCCESS;
2323 struct ieee80211_channel chan;
2324 tANI_U8 finalLen = 0;
2325 tANI_U8 *finalBuf = NULL;
2326 tANI_U8 temp = 0;
2327 u64 cookie;
2328 hdd_station_ctx_t *pHddStaCtx = NULL;
2329 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2330
2331 /* if not associated, no need to send action frame */
2332 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2333 {
2334 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2335 ret = -EINVAL;
2336 goto exit;
2337 }
2338
2339 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2340 &dwellTime, &buf, &bufLen);
2341 if (eHAL_STATUS_SUCCESS != status)
2342 {
2343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2344 "%s: Failed to parse send action frame data", __func__);
2345 ret = -EINVAL;
2346 goto exit;
2347 }
2348
2349 /* if the target bssid is different from currently associated AP,
2350 then no need to send action frame */
2351 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2352 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2353 {
2354 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2355 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002356 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002357 goto exit;
2358 }
2359
2360 /* if the channel number is different from operating channel then
2361 no need to send action frame */
2362 if (channel != pHddStaCtx->conn_info.operationChannel)
2363 {
2364 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2365 "%s: channel(%d) is different from operating channel(%d)",
2366 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2367 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002368 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002369 goto exit;
2370 }
2371 chan.center_freq = sme_ChnToFreq(channel);
2372
2373 finalLen = bufLen + 24;
2374 finalBuf = vos_mem_malloc(finalLen);
2375 if (NULL == finalBuf)
2376 {
2377 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2378 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002379 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002380 goto exit;
2381 }
2382 vos_mem_zero(finalBuf, finalLen);
2383
2384 /* Fill subtype */
2385 temp = SIR_MAC_MGMT_ACTION << 4;
2386 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2387
2388 /* Fill type */
2389 temp = SIR_MAC_MGMT_FRAME;
2390 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2391
2392 /* Fill destination address (bssid of the AP) */
2393 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2394
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002395 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002396 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2397
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002398 /* Fill BSSID (AP mac address) */
2399 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002400
2401 /* Fill received buffer from 24th address */
2402 vos_mem_copy(finalBuf + 24, buf, bufLen);
2403
Jeff Johnson11c33152013-04-16 17:52:40 -07002404 /* done with the parsed buffer */
2405 vos_mem_free(buf);
2406
Yue Maf49ba872013-08-19 12:04:25 -07002407 wlan_hdd_action( NULL,
2408#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2409 &(pAdapter->wdev),
2410#else
2411 dev,
2412#endif
2413 &chan, 0,
2414#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2415 NL80211_CHAN_HT20, 1,
2416#endif
2417 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002418 1, &cookie );
2419 vos_mem_free(finalBuf);
2420 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002421 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2422 {
2423 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2424 char extra[32];
2425 tANI_U8 len = 0;
2426
2427 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002428 len = scnprintf(extra, sizeof(extra), "%s %d",
2429 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002430 if (copy_to_user(priv_data.buf, &extra, len + 1))
2431 {
2432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2433 "%s: failed to copy data to user buffer", __func__);
2434 ret = -EFAULT;
2435 goto exit;
2436 }
2437 }
2438 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2439 {
2440 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002441 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002442 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002443
2444 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2445 value = value + 19;
2446 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002447 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002448 if (ret < 0)
2449 {
2450 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002451 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002453 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002454 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2455 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2456 ret = -EINVAL;
2457 goto exit;
2458 }
2459
2460 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2461 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2462 {
2463 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2464 "lfr mode value %d is out of range"
2465 " (Min: %d Max: %d)", maxTime,
2466 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2467 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2468 ret = -EINVAL;
2469 goto exit;
2470 }
2471
2472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2473 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2474
2475 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002476
2477 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2478 * where RFS is the RF Switching time. It is twice RFS to consider the
2479 * time to go off channel and return to the home channel. */
2480 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2481 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2482 {
2483 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002484 "%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 -07002485 " Hence enforcing home away time to disable (0)",
2486 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2487 homeAwayTime = 0;
2488 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2489 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2490 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002491 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2492 }
2493 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2494 {
2495 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2496 char extra[32];
2497 tANI_U8 len = 0;
2498
2499 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002500 len = scnprintf(extra, sizeof(extra), "%s %d",
2501 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002502 if (copy_to_user(priv_data.buf, &extra, len + 1))
2503 {
2504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2505 "%s: failed to copy data to user buffer", __func__);
2506 ret = -EFAULT;
2507 goto exit;
2508 }
2509 }
2510 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2511 {
2512 tANI_U8 *value = command;
2513 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2514
2515 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2516 value = value + 16;
2517 /* Convert the value from ascii to integer */
2518 ret = kstrtou16(value, 10, &val);
2519 if (ret < 0)
2520 {
2521 /* If the input value is greater than max value of datatype, then also
2522 kstrtou16 fails */
2523 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2524 "%s: kstrtou16 failed range [%d - %d]", __func__,
2525 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2526 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2527 ret = -EINVAL;
2528 goto exit;
2529 }
2530
2531 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2532 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2533 {
2534 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2535 "scan home time value %d is out of range"
2536 " (Min: %d Max: %d)", val,
2537 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2538 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2539 ret = -EINVAL;
2540 goto exit;
2541 }
2542
2543 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2544 "%s: Received Command to change scan home time = %d", __func__, val);
2545
2546 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2547 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2548 }
2549 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2550 {
2551 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2552 char extra[32];
2553 tANI_U8 len = 0;
2554
2555 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002556 len = scnprintf(extra, sizeof(extra), "%s %d",
2557 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002558 if (copy_to_user(priv_data.buf, &extra, len + 1))
2559 {
2560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2561 "%s: failed to copy data to user buffer", __func__);
2562 ret = -EFAULT;
2563 goto exit;
2564 }
2565 }
2566 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2567 {
2568 tANI_U8 *value = command;
2569 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2570
2571 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2572 value = value + 17;
2573 /* Convert the value from ascii to integer */
2574 ret = kstrtou8(value, 10, &val);
2575 if (ret < 0)
2576 {
2577 /* If the input value is greater than max value of datatype, then also
2578 kstrtou8 fails */
2579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2580 "%s: kstrtou8 failed range [%d - %d]", __func__,
2581 CFG_ROAM_INTRA_BAND_MIN,
2582 CFG_ROAM_INTRA_BAND_MAX);
2583 ret = -EINVAL;
2584 goto exit;
2585 }
2586
2587 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2588 (val > CFG_ROAM_INTRA_BAND_MAX))
2589 {
2590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2591 "intra band mode value %d is out of range"
2592 " (Min: %d Max: %d)", val,
2593 CFG_ROAM_INTRA_BAND_MIN,
2594 CFG_ROAM_INTRA_BAND_MAX);
2595 ret = -EINVAL;
2596 goto exit;
2597 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2599 "%s: Received Command to change intra band = %d", __func__, val);
2600
2601 pHddCtx->cfg_ini->nRoamIntraBand = val;
2602 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2603 }
2604 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2605 {
2606 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2607 char extra[32];
2608 tANI_U8 len = 0;
2609
2610 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002611 len = scnprintf(extra, sizeof(extra), "%s %d",
2612 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002613 if (copy_to_user(priv_data.buf, &extra, len + 1))
2614 {
2615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2616 "%s: failed to copy data to user buffer", __func__);
2617 ret = -EFAULT;
2618 goto exit;
2619 }
2620 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002621 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2622 {
2623 tANI_U8 *value = command;
2624 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2625
2626 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2627 value = value + 15;
2628 /* Convert the value from ascii to integer */
2629 ret = kstrtou8(value, 10, &nProbes);
2630 if (ret < 0)
2631 {
2632 /* If the input value is greater than max value of datatype, then also
2633 kstrtou8 fails */
2634 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2635 "%s: kstrtou8 failed range [%d - %d]", __func__,
2636 CFG_ROAM_SCAN_N_PROBES_MIN,
2637 CFG_ROAM_SCAN_N_PROBES_MAX);
2638 ret = -EINVAL;
2639 goto exit;
2640 }
2641
2642 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2643 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2644 {
2645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2646 "NProbes value %d is out of range"
2647 " (Min: %d Max: %d)", nProbes,
2648 CFG_ROAM_SCAN_N_PROBES_MIN,
2649 CFG_ROAM_SCAN_N_PROBES_MAX);
2650 ret = -EINVAL;
2651 goto exit;
2652 }
2653
2654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2655 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2656
2657 pHddCtx->cfg_ini->nProbes = nProbes;
2658 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2659 }
2660 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2661 {
2662 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2663 char extra[32];
2664 tANI_U8 len = 0;
2665
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002666 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002667 if (copy_to_user(priv_data.buf, &extra, len + 1))
2668 {
2669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2670 "%s: failed to copy data to user buffer", __func__);
2671 ret = -EFAULT;
2672 goto exit;
2673 }
2674 }
2675 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2676 {
2677 tANI_U8 *value = command;
2678 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002679 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002680
2681 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2682 /* input value is in units of msec */
2683 value = value + 20;
2684 /* Convert the value from ascii to integer */
2685 ret = kstrtou16(value, 10, &homeAwayTime);
2686 if (ret < 0)
2687 {
2688 /* If the input value is greater than max value of datatype, then also
2689 kstrtou8 fails */
2690 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2691 "%s: kstrtou8 failed range [%d - %d]", __func__,
2692 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2693 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2694 ret = -EINVAL;
2695 goto exit;
2696 }
2697
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002698 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2699 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2700 {
2701 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2702 "homeAwayTime value %d is out of range"
2703 " (Min: %d Max: %d)", homeAwayTime,
2704 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2705 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2706 ret = -EINVAL;
2707 goto exit;
2708 }
2709
2710 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2711 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2712
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002713 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2714 * where RFS is the RF Switching time. It is twice RFS to consider the
2715 * time to go off channel and return to the home channel. */
2716 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2717 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2718 {
2719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002720 "%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 -07002721 " Hence enforcing home away time to disable (0)",
2722 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2723 homeAwayTime = 0;
2724 }
2725
2726 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2727 {
2728 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2729 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2730 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002731 }
2732 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2733 {
2734 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2735 char extra[32];
2736 tANI_U8 len = 0;
2737
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002738 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002739 if (copy_to_user(priv_data.buf, &extra, len + 1))
2740 {
2741 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2742 "%s: failed to copy data to user buffer", __func__);
2743 ret = -EFAULT;
2744 goto exit;
2745 }
2746 }
2747 else if (strncmp(command, "REASSOC", 7) == 0)
2748 {
2749 tANI_U8 *value = command;
2750 tANI_U8 channel = 0;
2751 tSirMacAddr targetApBssid;
2752 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002753#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2754 tCsrHandoffRequest handoffInfo;
2755#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002756 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002757 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2758
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002759 /* if not associated, no need to proceed with reassoc */
2760 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2761 {
2762 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2763 ret = -EINVAL;
2764 goto exit;
2765 }
2766
2767 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2768 if (eHAL_STATUS_SUCCESS != status)
2769 {
2770 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2771 "%s: Failed to parse reassoc command data", __func__);
2772 ret = -EINVAL;
2773 goto exit;
2774 }
2775
2776 /* if the target bssid is same as currently associated AP,
2777 then no need to proceed with reassoc */
2778 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2779 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2780 {
2781 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2782 ret = -EINVAL;
2783 goto exit;
2784 }
2785
2786 /* Check channel number is a valid channel number */
2787 if(VOS_STATUS_SUCCESS !=
2788 wlan_hdd_validate_operation_channel(pAdapter, channel))
2789 {
2790 hddLog(VOS_TRACE_LEVEL_ERROR,
2791 "%s: Invalid Channel [%d] \n", __func__, channel);
2792 return -EINVAL;
2793 }
2794
2795 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002796#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2797 handoffInfo.channel = channel;
2798 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2799 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2800#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002801 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002802 else if (strncmp(command, "SETWESMODE", 10) == 0)
2803 {
2804 tANI_U8 *value = command;
2805 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2806
2807 /* Move pointer to ahead of SETWESMODE<delimiter> */
2808 value = value + 11;
2809 /* Convert the value from ascii to integer */
2810 ret = kstrtou8(value, 10, &wesMode);
2811 if (ret < 0)
2812 {
2813 /* If the input value is greater than max value of datatype, then also
2814 kstrtou8 fails */
2815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2816 "%s: kstrtou8 failed range [%d - %d]", __func__,
2817 CFG_ENABLE_WES_MODE_NAME_MIN,
2818 CFG_ENABLE_WES_MODE_NAME_MAX);
2819 ret = -EINVAL;
2820 goto exit;
2821 }
2822
2823 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2824 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2825 {
2826 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2827 "WES Mode value %d is out of range"
2828 " (Min: %d Max: %d)", wesMode,
2829 CFG_ENABLE_WES_MODE_NAME_MIN,
2830 CFG_ENABLE_WES_MODE_NAME_MAX);
2831 ret = -EINVAL;
2832 goto exit;
2833 }
2834 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2835 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2836
2837 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2838 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2839 }
2840 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2841 {
2842 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2843 char extra[32];
2844 tANI_U8 len = 0;
2845
Arif Hussain826d9412013-11-12 16:44:54 -08002846 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002847 if (copy_to_user(priv_data.buf, &extra, len + 1))
2848 {
2849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2850 "%s: failed to copy data to user buffer", __func__);
2851 ret = -EFAULT;
2852 goto exit;
2853 }
2854 }
2855#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002856#ifdef FEATURE_WLAN_LFR
2857 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2858 {
2859 tANI_U8 *value = command;
2860 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2861
2862 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2863 value = value + 12;
2864 /* Convert the value from ascii to integer */
2865 ret = kstrtou8(value, 10, &lfrMode);
2866 if (ret < 0)
2867 {
2868 /* If the input value is greater than max value of datatype, then also
2869 kstrtou8 fails */
2870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2871 "%s: kstrtou8 failed range [%d - %d]", __func__,
2872 CFG_LFR_FEATURE_ENABLED_MIN,
2873 CFG_LFR_FEATURE_ENABLED_MAX);
2874 ret = -EINVAL;
2875 goto exit;
2876 }
2877
2878 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2879 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2880 {
2881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2882 "lfr mode value %d is out of range"
2883 " (Min: %d Max: %d)", lfrMode,
2884 CFG_LFR_FEATURE_ENABLED_MIN,
2885 CFG_LFR_FEATURE_ENABLED_MAX);
2886 ret = -EINVAL;
2887 goto exit;
2888 }
2889
2890 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2891 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2892
2893 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2894 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2895 }
2896#endif
2897#ifdef WLAN_FEATURE_VOWIFI_11R
2898 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2899 {
2900 tANI_U8 *value = command;
2901 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2902
2903 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2904 value = value + 18;
2905 /* Convert the value from ascii to integer */
2906 ret = kstrtou8(value, 10, &ft);
2907 if (ret < 0)
2908 {
2909 /* If the input value is greater than max value of datatype, then also
2910 kstrtou8 fails */
2911 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2912 "%s: kstrtou8 failed range [%d - %d]", __func__,
2913 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2914 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2915 ret = -EINVAL;
2916 goto exit;
2917 }
2918
2919 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2920 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2921 {
2922 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2923 "ft mode value %d is out of range"
2924 " (Min: %d Max: %d)", ft,
2925 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2926 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2927 ret = -EINVAL;
2928 goto exit;
2929 }
2930
2931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2932 "%s: Received Command to change ft mode = %d", __func__, ft);
2933
2934 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2935 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2936 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302937
2938 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2939 {
2940 tANI_U8 *value = command;
2941 tSirMacAddr targetApBssid;
2942 tANI_U8 trigger = 0;
2943 eHalStatus status = eHAL_STATUS_SUCCESS;
2944 hdd_station_ctx_t *pHddStaCtx = NULL;
2945 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2946
2947 /* if not associated, no need to proceed with reassoc */
2948 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2949 {
2950 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2951 ret = -EINVAL;
2952 goto exit;
2953 }
2954
2955 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2956 if (eHAL_STATUS_SUCCESS != status)
2957 {
2958 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2959 "%s: Failed to parse reassoc command data", __func__);
2960 ret = -EINVAL;
2961 goto exit;
2962 }
2963
2964 /* if the target bssid is same as currently associated AP,
2965 then no need to proceed with reassoc */
2966 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2967 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2968 {
2969 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2970 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2971 __func__);
2972 ret = -EINVAL;
2973 goto exit;
2974 }
2975
2976 /* Proceed with scan/roam */
2977 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2978 &targetApBssid[0],
2979 (tSmeFastRoamTrigger)(trigger));
2980 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002981#endif
2982#ifdef FEATURE_WLAN_CCX
2983 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2984 {
2985 tANI_U8 *value = command;
2986 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2987
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002988 /* Check if the features OKC/CCX/11R are supported simultaneously,
2989 then this operation is not permitted (return FAILURE) */
2990 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2991 hdd_is_okc_mode_enabled(pHddCtx) &&
2992 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2993 {
2994 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2995 "%s: OKC/CCX/11R are supported simultaneously"
2996 " hence this operation is not permitted!", __func__);
2997 ret = -EPERM;
2998 goto exit;
2999 }
3000
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003001 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3002 value = value + 11;
3003 /* Convert the value from ascii to integer */
3004 ret = kstrtou8(value, 10, &ccxMode);
3005 if (ret < 0)
3006 {
3007 /* If the input value is greater than max value of datatype, then also
3008 kstrtou8 fails */
3009 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3010 "%s: kstrtou8 failed range [%d - %d]", __func__,
3011 CFG_CCX_FEATURE_ENABLED_MIN,
3012 CFG_CCX_FEATURE_ENABLED_MAX);
3013 ret = -EINVAL;
3014 goto exit;
3015 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003016 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
3017 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
3018 {
3019 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3020 "Ccx mode value %d is out of range"
3021 " (Min: %d Max: %d)", ccxMode,
3022 CFG_CCX_FEATURE_ENABLED_MIN,
3023 CFG_CCX_FEATURE_ENABLED_MAX);
3024 ret = -EINVAL;
3025 goto exit;
3026 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003027 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3028 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3029
3030 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3031 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3032 }
3033#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003034 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3035 {
3036 tANI_U8 *value = command;
3037 tANI_BOOLEAN roamScanControl = 0;
3038
3039 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3040 value = value + 19;
3041 /* Convert the value from ascii to integer */
3042 ret = kstrtou8(value, 10, &roamScanControl);
3043 if (ret < 0)
3044 {
3045 /* If the input value is greater than max value of datatype, then also
3046 kstrtou8 fails */
3047 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3048 "%s: kstrtou8 failed ", __func__);
3049 ret = -EINVAL;
3050 goto exit;
3051 }
3052
3053 if (0 != roamScanControl)
3054 {
3055 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3056 "roam scan control invalid value = %d",
3057 roamScanControl);
3058 ret = -EINVAL;
3059 goto exit;
3060 }
3061 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3062 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3063
3064 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3065 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003066#ifdef FEATURE_WLAN_OKC
3067 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3068 {
3069 tANI_U8 *value = command;
3070 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3071
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003072 /* Check if the features OKC/CCX/11R are supported simultaneously,
3073 then this operation is not permitted (return FAILURE) */
3074 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3075 hdd_is_okc_mode_enabled(pHddCtx) &&
3076 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3077 {
3078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3079 "%s: OKC/CCX/11R are supported simultaneously"
3080 " hence this operation is not permitted!", __func__);
3081 ret = -EPERM;
3082 goto exit;
3083 }
3084
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003085 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3086 value = value + 11;
3087 /* Convert the value from ascii to integer */
3088 ret = kstrtou8(value, 10, &okcMode);
3089 if (ret < 0)
3090 {
3091 /* If the input value is greater than max value of datatype, then also
3092 kstrtou8 fails */
3093 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3094 "%s: kstrtou8 failed range [%d - %d]", __func__,
3095 CFG_OKC_FEATURE_ENABLED_MIN,
3096 CFG_OKC_FEATURE_ENABLED_MAX);
3097 ret = -EINVAL;
3098 goto exit;
3099 }
3100
3101 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3102 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3103 {
3104 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3105 "Okc mode value %d is out of range"
3106 " (Min: %d Max: %d)", okcMode,
3107 CFG_OKC_FEATURE_ENABLED_MIN,
3108 CFG_OKC_FEATURE_ENABLED_MAX);
3109 ret = -EINVAL;
3110 goto exit;
3111 }
3112
3113 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3114 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3115
3116 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3117 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003118#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003119 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3120 {
3121 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3122 char extra[32];
3123 tANI_U8 len = 0;
3124
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003125 len = scnprintf(extra, sizeof(extra), "%s %d",
3126 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003127 if (copy_to_user(priv_data.buf, &extra, len + 1))
3128 {
3129 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3130 "%s: failed to copy data to user buffer", __func__);
3131 ret = -EFAULT;
3132 goto exit;
3133 }
3134 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303135#ifdef WLAN_FEATURE_PACKET_FILTERING
3136 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3137 {
3138 tANI_U8 filterType = 0;
3139 tANI_U8 *value = command;
3140
3141 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3142 value = value + 22;
3143
3144 /* Convert the value from ascii to integer */
3145 ret = kstrtou8(value, 10, &filterType);
3146 if (ret < 0)
3147 {
3148 /* If the input value is greater than max value of datatype,
3149 * then also kstrtou8 fails
3150 */
3151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3152 "%s: kstrtou8 failed range ", __func__);
3153 ret = -EINVAL;
3154 goto exit;
3155 }
3156
3157 if (filterType != 0 && filterType != 1)
3158 {
3159 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3160 "%s: Accepted Values are 0 and 1 ", __func__);
3161 ret = -EINVAL;
3162 goto exit;
3163 }
3164 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3165 pAdapter->sessionId);
3166 }
3167#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303168 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3169 {
3170 char *dhcpPhase;
3171 dhcpPhase = command + 12;
3172 if ('1' == *dhcpPhase)
3173 {
3174 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3175 pAdapter->macAddressCurrent.bytes);
3176 }
3177 else if ('2' == *dhcpPhase)
3178 {
3179 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3180 pAdapter->macAddressCurrent.bytes);
3181 }
3182 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003183 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3184 {
3185 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3186 }
3187 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3188 {
3189 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3190 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303191 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3192 {
3193 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3194 char extra[32];
3195 tANI_U8 len = 0;
3196
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003197 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303198 (int)pCfg->nActiveMaxChnTime);
3199 if (copy_to_user(priv_data.buf, &extra, len + 1))
3200 {
3201 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3202 "%s: failed to copy data to user buffer", __func__);
3203 ret = -EFAULT;
3204 goto exit;
3205 }
3206 ret = len;
3207 }
3208 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3209 {
3210 tANI_U8 *value = command;
3211 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3212 int val = 0, temp;
3213
3214 value = value + 13;
3215 temp = kstrtou32(value, 10, &val);
3216 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3217 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3218 {
3219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3220 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3221 ret = -EFAULT;
3222 goto exit;
3223 }
3224 pCfg->nActiveMaxChnTime = val;
3225 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003226 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3227 {
3228 tANI_U8 filterType = 0;
3229 tANI_U8 *value;
3230 value = command + 9;
3231
3232 /* Convert the value from ascii to integer */
3233 ret = kstrtou8(value, 10, &filterType);
3234 if (ret < 0)
3235 {
3236 /* If the input value is greater than max value of datatype,
3237 * then also kstrtou8 fails
3238 */
3239 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3240 "%s: kstrtou8 failed range ", __func__);
3241 ret = -EINVAL;
3242 goto exit;
3243 }
3244 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3245 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3246 {
3247 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3248 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3249 " 2-Sink ", __func__);
3250 ret = -EINVAL;
3251 goto exit;
3252 }
3253 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3254 pHddCtx->drvr_miracast = filterType;
3255 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3256 }
Leo Chang614d2072013-08-22 14:59:44 -07003257 else if (strncmp(command, "SETMCRATE", 9) == 0)
3258 {
Leo Chang614d2072013-08-22 14:59:44 -07003259 tANI_U8 *value = command;
3260 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003261 tSirRateUpdateInd *rateUpdate;
3262 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003263
3264 /* Only valid for SAP mode */
3265 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3266 {
3267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3268 "%s: SAP mode is not running", __func__);
3269 ret = -EFAULT;
3270 goto exit;
3271 }
3272
3273 /* Move pointer to ahead of SETMCRATE<delimiter> */
3274 /* input value is in units of hundred kbps */
3275 value = value + 10;
3276 /* Convert the value from ascii to integer, decimal base */
3277 ret = kstrtouint(value, 10, &targetRate);
3278
Leo Chang1f98cbd2013-10-17 15:03:52 -07003279 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3280 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003281 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003282 hddLog(VOS_TRACE_LEVEL_ERROR,
3283 "%s: SETMCRATE indication alloc fail", __func__);
3284 ret = -EFAULT;
3285 goto exit;
3286 }
3287 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3288
3289 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3290 "MC Target rate %d", targetRate);
3291 /* Ignore unicast */
3292 rateUpdate->ucastDataRate = -1;
3293 rateUpdate->mcastDataRate24GHz = targetRate;
3294 rateUpdate->mcastDataRate5GHz = targetRate;
3295 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3296 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3297 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3298 if (eHAL_STATUS_SUCCESS != status)
3299 {
3300 hddLog(VOS_TRACE_LEVEL_ERROR,
3301 "%s: SET_MC_RATE failed", __func__);
3302 vos_mem_free(rateUpdate);
3303 ret = -EFAULT;
3304 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003305 }
3306 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303307#ifdef FEATURE_WLAN_BATCH_SCAN
3308 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3309 {
3310 char extra[32];
3311 tANI_U8 len = 0;
3312 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3313
3314 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3315 {
3316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3317 "%s: Batch scan feature is not supported by FW", __func__);
3318 ret = -EINVAL;
3319 goto exit;
3320 }
3321
3322 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3323 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3324 {
3325 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3326 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3327 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3328 " mode",
3329 pAdapter->device_mode);
3330 ret = -EINVAL;
3331 goto exit;
3332 }
3333
Arif Hussain826d9412013-11-12 16:44:54 -08003334 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
Rajeev79dbe4c2013-10-05 11:03:42 +05303335 version);
3336 if (copy_to_user(priv_data.buf, &extra, len + 1))
3337 {
3338 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3339 "%s: failed to copy data to user buffer", __func__);
3340 ret = -EFAULT;
3341 goto exit;
3342 }
3343 ret = HDD_BATCH_SCAN_VERSION;
3344 }
3345 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3346 {
3347 int status;
3348 tANI_U8 *value = (command + 16);
3349 eHalStatus halStatus;
3350 unsigned long rc;
3351 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3352 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3353
3354 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3355 {
3356 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3357 "%s: Batch scan feature is not supported by FW", __func__);
3358 ret = -EINVAL;
3359 goto exit;
3360 }
3361
Rajeev Kumar20140c12013-10-21 19:39:02 -07003362
Rajeev79dbe4c2013-10-05 11:03:42 +05303363 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3364 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3365 {
3366 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003367 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303368 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3369 pAdapter->device_mode);
3370 ret = -EINVAL;
3371 goto exit;
3372 }
3373
Rajeev Kumar20140c12013-10-21 19:39:02 -07003374
Rajeev79dbe4c2013-10-05 11:03:42 +05303375 status = hdd_parse_set_batchscan_command(value, pReq);
3376 if (status)
3377 {
3378 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003379 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303380 ret = -EINVAL;
3381 goto exit;
3382 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003383
3384
Rajeev79dbe4c2013-10-05 11:03:42 +05303385 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3386 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3387 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3388 pAdapter);
3389
3390 if ( eHAL_STATUS_SUCCESS == halStatus )
3391 {
3392 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3393 "sme_SetBatchScanReq returned success halStatus %d",
3394 halStatus);
3395 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3396 {
3397 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3398 rc = wait_for_completion_timeout(
3399 &pAdapter->hdd_set_batch_scan_req_var,
3400 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3401 if (0 == rc)
3402 {
3403 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3404 "%s: Timeout waiting for set batch scan to complete",
3405 __func__);
3406 ret = -EINVAL;
3407 goto exit;
3408 }
3409 }
3410 if ( !pRsp->nScansToBatch )
3411 {
3412 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3413 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003414 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303415 ret = -EINVAL;
3416 goto exit;
3417 }
3418 /*As per the Batch Scan Framework API we should return the MIN of
3419 either MSCAN or the max # of scans firmware can cache*/
3420 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3421
Rajeev Kumar20140c12013-10-21 19:39:02 -07003422 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3423
Rajeev79dbe4c2013-10-05 11:03:42 +05303424 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3425 "%s: request MSCAN %d response MSCAN %d ret %d",
3426 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3427 }
3428 else
3429 {
3430 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3431 "sme_SetBatchScanReq returned failure halStatus %d",
3432 halStatus);
3433 ret = -EINVAL;
3434 goto exit;
3435 }
3436 }
3437 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3438 {
3439 eHalStatus halStatus;
3440 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3441 pInd->param = 0;
3442
3443 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3444 {
3445 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3446 "%s: Batch scan feature is not supported by FW", __func__);
3447 ret = -EINVAL;
3448 goto exit;
3449 }
3450
Rajeev Kumar20140c12013-10-21 19:39:02 -07003451 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303452 {
3453 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003454 "Batch scan is not yet enabled batch scan state %d",
3455 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303456 ret = -EINVAL;
3457 goto exit;
3458 }
3459
Rajeev Kumar20140c12013-10-21 19:39:02 -07003460 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3461
Rajeev79dbe4c2013-10-05 11:03:42 +05303462 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3463 pAdapter->sessionId);
3464 if ( eHAL_STATUS_SUCCESS == halStatus )
3465 {
3466 ret = 0;
3467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3468 "sme_StopBatchScanInd returned success halStatus %d",
3469 halStatus);
3470 }
3471 else
3472 {
3473 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3474 "sme_StopBatchScanInd returned failure halStatus %d",
3475 halStatus);
3476 ret = -EINVAL;
3477 goto exit;
3478 }
3479 }
3480 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3481 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003482 tANI_U32 remain_len;
3483
Rajeev79dbe4c2013-10-05 11:03:42 +05303484 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3485 {
3486 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3487 "%s: Batch scan feature is not supported by FW", __func__);
3488 ret = -EINVAL;
3489 goto exit;
3490 }
3491
Rajeev Kumar20140c12013-10-21 19:39:02 -07003492 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303493 {
3494 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003495 "Batch scan is not yet enabled could not return results"
3496 "Batch Scan state %d",
3497 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303498 ret = -EINVAL;
3499 goto exit;
3500 }
3501
3502 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003503 remain_len = priv_data.total_len - priv_data.used_len;
3504 if (remain_len < priv_data.total_len)
3505 {
3506 /*Clear previous batch scan response data if any*/
3507 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3508 }
3509 else
3510 {
3511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3512 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003513 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003514 priv_data.total_len, priv_data.used_len, remain_len);
3515 ret = -EINVAL;
3516 goto exit;
3517 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303518 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3519 }
3520#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003521#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3522 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3523 {
3524 tANI_U8 *value = command;
3525 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3526 tANI_U8 numChannels = 0;
3527 eHalStatus status = eHAL_STATUS_SUCCESS;
3528
3529 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3530 if (eHAL_STATUS_SUCCESS != status)
3531 {
3532 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3533 "%s: Failed to parse channel list information", __func__);
3534 ret = -EINVAL;
3535 goto exit;
3536 }
3537
3538 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3539 {
3540 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3541 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3542 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3543 ret = -EINVAL;
3544 goto exit;
3545 }
3546 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3547 ChannelList,
3548 numChannels);
3549 if (eHAL_STATUS_SUCCESS != status)
3550 {
3551 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3552 "%s: Failed to update channel list information", __func__);
3553 ret = -EINVAL;
3554 goto exit;
3555 }
3556 }
3557 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3558 {
3559 tANI_U8 *value = command;
3560 char extra[128] = {0};
3561 int len = 0;
3562 tANI_U8 tid = 0;
3563 hdd_station_ctx_t *pHddStaCtx = NULL;
3564 tAniTrafStrmMetrics tsmMetrics;
3565 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3566
3567 /* if not associated, return error */
3568 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3569 {
3570 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3571 ret = -EINVAL;
3572 goto exit;
3573 }
3574
3575 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3576 value = value + 12;
3577 /* Convert the value from ascii to integer */
3578 ret = kstrtou8(value, 10, &tid);
3579 if (ret < 0)
3580 {
3581 /* If the input value is greater than max value of datatype, then also
3582 kstrtou8 fails */
3583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3584 "%s: kstrtou8 failed range [%d - %d]", __func__,
3585 TID_MIN_VALUE,
3586 TID_MAX_VALUE);
3587 ret = -EINVAL;
3588 goto exit;
3589 }
3590
3591 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3592 {
3593 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3594 "tid value %d is out of range"
3595 " (Min: %d Max: %d)", tid,
3596 TID_MIN_VALUE,
3597 TID_MAX_VALUE);
3598 ret = -EINVAL;
3599 goto exit;
3600 }
3601
3602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3603 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3604
3605 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3606 {
3607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3608 "%s: failed to get tsm stats", __func__);
3609 ret = -EFAULT;
3610 goto exit;
3611 }
3612
3613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3614 "UplinkPktQueueDly(%d)\n"
3615 "UplinkPktQueueDlyHist[0](%d)\n"
3616 "UplinkPktQueueDlyHist[1](%d)\n"
3617 "UplinkPktQueueDlyHist[2](%d)\n"
3618 "UplinkPktQueueDlyHist[3](%d)\n"
3619 "UplinkPktTxDly(%lu)\n"
3620 "UplinkPktLoss(%d)\n"
3621 "UplinkPktCount(%d)\n"
3622 "RoamingCount(%d)\n"
3623 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3624 tsmMetrics.UplinkPktQueueDlyHist[0],
3625 tsmMetrics.UplinkPktQueueDlyHist[1],
3626 tsmMetrics.UplinkPktQueueDlyHist[2],
3627 tsmMetrics.UplinkPktQueueDlyHist[3],
3628 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3629 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3630
3631 /* Output TSM stats is of the format
3632 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3633 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003634 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003635 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3636 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3637 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3638 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3639 tsmMetrics.RoamingDly);
3640
3641 if (copy_to_user(priv_data.buf, &extra, len + 1))
3642 {
3643 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3644 "%s: failed to copy data to user buffer", __func__);
3645 ret = -EFAULT;
3646 goto exit;
3647 }
3648 }
3649 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3650 {
3651 tANI_U8 *value = command;
3652 tANI_U8 *cckmIe = NULL;
3653 tANI_U8 cckmIeLen = 0;
3654 eHalStatus status = eHAL_STATUS_SUCCESS;
3655
3656 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3657 if (eHAL_STATUS_SUCCESS != status)
3658 {
3659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3660 "%s: Failed to parse cckm ie data", __func__);
3661 ret = -EINVAL;
3662 goto exit;
3663 }
3664
3665 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3666 {
3667 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3668 "%s: CCKM Ie input length is more than max[%d]", __func__,
3669 DOT11F_IE_RSN_MAX_LEN);
3670 if (NULL != cckmIe)
3671 {
3672 vos_mem_free(cckmIe);
3673 }
3674 ret = -EINVAL;
3675 goto exit;
3676 }
3677 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3678 if (NULL != cckmIe)
3679 {
3680 vos_mem_free(cckmIe);
3681 }
3682 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003683 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3684 {
3685 tANI_U8 *value = command;
3686 tCsrCcxBeaconReq ccxBcnReq;
3687 eHalStatus status = eHAL_STATUS_SUCCESS;
3688 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3689 if (eHAL_STATUS_SUCCESS != status)
3690 {
3691 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3692 "%s: Failed to parse ccx beacon req", __func__);
3693 ret = -EINVAL;
3694 goto exit;
3695 }
3696
3697 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3698 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003699#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003700 else {
3701 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3702 __func__, command);
3703 }
3704
Jeff Johnson295189b2012-06-20 16:38:30 -07003705 }
3706exit:
3707 if (command)
3708 {
3709 kfree(command);
3710 }
3711 return ret;
3712}
3713
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003714
3715
3716#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003717/**---------------------------------------------------------------------------
3718
3719 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3720
3721 This function parses the ccx beacon request passed in the format
3722 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3723 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3724 <space>Scan Mode N<space>Meas Duration N
3725 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3726 then take N.
3727 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3728 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3729 This function does not take care of removing duplicate channels from the list
3730
3731 \param - pValue Pointer to data
3732 \param - pCcxBcnReq output pointer to store parsed ie information
3733
3734 \return - 0 for success non-zero for failure
3735
3736 --------------------------------------------------------------------------*/
3737static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3738 tCsrCcxBeaconReq *pCcxBcnReq)
3739{
3740 tANI_U8 *inPtr = pValue;
3741 int tempInt = 0;
3742 int j = 0, i = 0, v = 0;
3743 char buf[32];
3744
3745 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3746 /*no argument after the command*/
3747 if (NULL == inPtr)
3748 {
3749 return -EINVAL;
3750 }
3751 /*no space after the command*/
3752 else if (SPACE_ASCII_VALUE != *inPtr)
3753 {
3754 return -EINVAL;
3755 }
3756
3757 /*removing empty spaces*/
3758 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3759
3760 /*no argument followed by spaces*/
3761 if ('\0' == *inPtr) return -EINVAL;
3762
3763 /*getting the first argument ie measurement token*/
3764 v = sscanf(inPtr, "%32s ", buf);
3765 if (1 != v) return -EINVAL;
3766
3767 v = kstrtos32(buf, 10, &tempInt);
3768 if ( v < 0) return -EINVAL;
3769
3770 pCcxBcnReq->numBcnReqIe = tempInt;
3771
3772 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3773 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3774
3775 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3776 {
3777 for (i = 0; i < 4; i++)
3778 {
3779 /*inPtr pointing to the beginning of first space after number of ie fields*/
3780 inPtr = strpbrk( inPtr, " " );
3781 /*no ie data after the number of ie fields argument*/
3782 if (NULL == inPtr) return -EINVAL;
3783
3784 /*removing empty space*/
3785 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3786
3787 /*no ie data after the number of ie fields argument and spaces*/
3788 if ( '\0' == *inPtr ) return -EINVAL;
3789
3790 v = sscanf(inPtr, "%32s ", buf);
3791 if (1 != v) return -EINVAL;
3792
3793 v = kstrtos32(buf, 10, &tempInt);
3794 if (v < 0) return -EINVAL;
3795
3796 switch (i)
3797 {
3798 case 0: /* Measurement token */
3799 if (tempInt <= 0)
3800 {
3801 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3802 "Invalid Measurement Token(%d)", tempInt);
3803 return -EINVAL;
3804 }
3805 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3806 break;
3807
3808 case 1: /* Channel number */
3809 if ((tempInt <= 0) ||
3810 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3811 {
3812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3813 "Invalid Channel Number(%d)", tempInt);
3814 return -EINVAL;
3815 }
3816 pCcxBcnReq->bcnReq[j].channel = tempInt;
3817 break;
3818
3819 case 2: /* Scan mode */
3820 if ((tempInt < 0) || (tempInt > 2))
3821 {
3822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3823 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3824 return -EINVAL;
3825 }
3826 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3827 break;
3828
3829 case 3: /* Measurement duration */
3830 if (tempInt <= 0)
3831 {
3832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3833 "Invalid Measurement Duration(%d)", tempInt);
3834 return -EINVAL;
3835 }
3836 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3837 break;
3838 }
3839 }
3840 }
3841
3842 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3843 {
3844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3845 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3846 j,
3847 pCcxBcnReq->bcnReq[j].measurementToken,
3848 pCcxBcnReq->bcnReq[j].channel,
3849 pCcxBcnReq->bcnReq[j].scanMode,
3850 pCcxBcnReq->bcnReq[j].measurementDuration);
3851 }
3852
3853 return VOS_STATUS_SUCCESS;
3854}
3855
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003856static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3857{
3858 struct statsContext *pStatsContext = NULL;
3859 hdd_adapter_t *pAdapter = NULL;
3860
3861 if (NULL == pContext)
3862 {
3863 hddLog(VOS_TRACE_LEVEL_ERROR,
3864 "%s: Bad param, pContext [%p]",
3865 __func__, pContext);
3866 return;
3867 }
3868
3869 /* there is a race condition that exists between this callback function
3870 and the caller since the caller could time out either before or
3871 while this code is executing. we'll assume the timeout hasn't
3872 occurred, but we'll verify that right before we save our work */
3873
3874 pStatsContext = pContext;
3875 pAdapter = pStatsContext->pAdapter;
3876 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3877 {
3878 /* the caller presumably timed out so there is nothing we can do */
3879 hddLog(VOS_TRACE_LEVEL_WARN,
3880 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3881 __func__, pAdapter, pStatsContext->magic);
3882 return;
3883 }
3884
3885 /* the race is on. caller could have timed out immediately after
3886 we verified the magic, but if so, caller will wait a short time
3887 for us to copy over the tsm stats */
3888 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3889 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3890 tsmMetrics.UplinkPktQueueDlyHist,
3891 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3892 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3893 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3894 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3895 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3896 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3897 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3898
3899 /* and notify the caller */
3900 complete(&pStatsContext->completion);
3901}
3902
3903
3904
3905static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3906 tAniTrafStrmMetrics* pTsmMetrics)
3907{
3908 hdd_station_ctx_t *pHddStaCtx = NULL;
3909 eHalStatus hstatus;
3910 long lrc;
3911 struct statsContext context;
3912 hdd_context_t *pHddCtx = NULL;
3913
3914 if (NULL == pAdapter)
3915 {
3916 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3917 return VOS_STATUS_E_FAULT;
3918 }
3919
3920 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3921 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3922
3923 /* we are connected prepare our callback context */
3924 init_completion(&context.completion);
3925 context.pAdapter = pAdapter;
3926 context.magic = STATS_CONTEXT_MAGIC;
3927
3928 /* query tsm stats */
3929 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3930 pHddStaCtx->conn_info.staId[ 0 ],
3931 pHddStaCtx->conn_info.bssId,
3932 &context, pHddCtx->pvosContext, tid);
3933
3934 if (eHAL_STATUS_SUCCESS != hstatus)
3935 {
3936 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3937 return hstatus;
3938 }
3939 else
3940 {
3941 /* request was sent -- wait for the response */
3942 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3943 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3944 /* either we have a response or we timed out
3945 either way, first invalidate our magic */
3946 context.magic = 0;
3947 if (lrc <= 0)
3948 {
3949 hddLog(VOS_TRACE_LEVEL_ERROR,
3950 "%s: SME %s while retrieving statistics",
3951 __func__, (0 == lrc) ? "timeout" : "interrupt");
3952 /* there is a race condition such that the callback
3953 function could be executing at the same time we are. of
3954 primary concern is if the callback function had already
3955 verified the "magic" but hasn't yet set the completion
3956 variable. Since the completion variable is on our
3957 stack, we'll delay just a bit to make sure the data is
3958 still valid if that is the case */
3959 msleep(50);
3960 return (VOS_STATUS_E_TIMEOUT);
3961 }
3962 }
3963 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3964 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3965 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3966 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3967 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3968 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3969 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3970 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3971 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3972 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3973
3974 return VOS_STATUS_SUCCESS;
3975}
3976#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3977
Srinivas Girigowdade697412013-02-14 16:31:48 -08003978#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3979void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3980{
3981 eCsrBand band = -1;
3982 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3983 switch (band)
3984 {
3985 case eCSR_BAND_ALL:
3986 *pBand = WLAN_HDD_UI_BAND_AUTO;
3987 break;
3988
3989 case eCSR_BAND_24:
3990 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3991 break;
3992
3993 case eCSR_BAND_5G:
3994 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3995 break;
3996
3997 default:
3998 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3999 *pBand = -1;
4000 break;
4001 }
4002}
4003
4004/**---------------------------------------------------------------------------
4005
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004006 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4007
4008 This function parses the send action frame data passed in the format
4009 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4010
Srinivas Girigowda56076852013-08-20 14:00:50 -07004011 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004012 \param - pTargetApBssid Pointer to target Ap bssid
4013 \param - pChannel Pointer to the Target AP channel
4014 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4015 \param - pBuf Pointer to data
4016 \param - pBufLen Pointer to data length
4017
4018 \return - 0 for success non-zero for failure
4019
4020 --------------------------------------------------------------------------*/
4021VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4022 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4023{
4024 tANI_U8 *inPtr = pValue;
4025 tANI_U8 *dataEnd;
4026 int tempInt;
4027 int j = 0;
4028 int i = 0;
4029 int v = 0;
4030 tANI_U8 tempBuf[32];
4031 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004032 /* 12 hexa decimal digits and 5 ':' */
4033 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004034
4035 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4036 /*no argument after the command*/
4037 if (NULL == inPtr)
4038 {
4039 return -EINVAL;
4040 }
4041
4042 /*no space after the command*/
4043 else if (SPACE_ASCII_VALUE != *inPtr)
4044 {
4045 return -EINVAL;
4046 }
4047
4048 /*removing empty spaces*/
4049 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4050
4051 /*no argument followed by spaces*/
4052 if ('\0' == *inPtr)
4053 {
4054 return -EINVAL;
4055 }
4056
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004057 v = sscanf(inPtr, "%17s", macAddress);
4058 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004059 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004060 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4061 "Invalid MAC address or All hex inputs are not read (%d)", v);
4062 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004063 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004064
4065 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4066 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4067 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4068 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4069 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4070 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004071
4072 /* point to the next argument */
4073 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4074 /*no argument after the command*/
4075 if (NULL == inPtr) return -EINVAL;
4076
4077 /*removing empty spaces*/
4078 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4079
4080 /*no argument followed by spaces*/
4081 if ('\0' == *inPtr)
4082 {
4083 return -EINVAL;
4084 }
4085
4086 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004087 v = sscanf(inPtr, "%32s ", tempBuf);
4088 if (1 != v) return -EINVAL;
4089
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004090 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304091 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4092 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004093
4094 *pChannel = tempInt;
4095
4096 /* point to the next argument */
4097 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4098 /*no argument after the command*/
4099 if (NULL == inPtr) return -EINVAL;
4100 /*removing empty spaces*/
4101 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4102
4103 /*no argument followed by spaces*/
4104 if ('\0' == *inPtr)
4105 {
4106 return -EINVAL;
4107 }
4108
4109 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004110 v = sscanf(inPtr, "%32s ", tempBuf);
4111 if (1 != v) return -EINVAL;
4112
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004113 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304114 if ( v < 0 || tempInt <= 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004115
4116 *pDwellTime = tempInt;
4117
4118 /* point to the next argument */
4119 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4120 /*no argument after the command*/
4121 if (NULL == inPtr) return -EINVAL;
4122 /*removing empty spaces*/
4123 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4124
4125 /*no argument followed by spaces*/
4126 if ('\0' == *inPtr)
4127 {
4128 return -EINVAL;
4129 }
4130
4131 /* find the length of data */
4132 dataEnd = inPtr;
4133 while(('\0' != *dataEnd) )
4134 {
4135 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004136 }
Kiet Lambe150c22013-11-21 16:30:32 +05304137 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004138 if ( *pBufLen <= 0) return -EINVAL;
4139
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004140 /* Allocate the number of bytes based on the number of input characters
4141 whether it is even or odd.
4142 if the number of input characters are even, then we need N/2 byte.
4143 if the number of input characters are odd, then we need do (N+1)/2 to
4144 compensate rounding off.
4145 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4146 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4147 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004148 if (NULL == *pBuf)
4149 {
4150 hddLog(VOS_TRACE_LEVEL_FATAL,
4151 "%s: vos_mem_alloc failed ", __func__);
4152 return -EINVAL;
4153 }
4154
4155 /* the buffer received from the upper layer is character buffer,
4156 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4157 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4158 and f0 in 3rd location */
4159 for (i = 0, j = 0; j < *pBufLen; j += 2)
4160 {
Kiet Lambe150c22013-11-21 16:30:32 +05304161 if( j+1 == *pBufLen)
4162 {
4163 tempByte = hdd_parse_hex(inPtr[j]);
4164 }
4165 else
4166 {
4167 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4168 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004169 (*pBuf)[i++] = tempByte;
4170 }
4171 *pBufLen = i;
4172 return VOS_STATUS_SUCCESS;
4173}
4174
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004175/**---------------------------------------------------------------------------
4176
Srinivas Girigowdade697412013-02-14 16:31:48 -08004177 \brief hdd_parse_channellist() - HDD Parse channel list
4178
4179 This function parses the channel list passed in the format
4180 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004181 if the Number of channels (N) does not match with the actual number of channels passed
4182 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4183 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4184 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4185 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004186
4187 \param - pValue Pointer to input channel list
4188 \param - ChannelList Pointer to local output array to record channel list
4189 \param - pNumChannels Pointer to number of roam scan channels
4190
4191 \return - 0 for success non-zero for failure
4192
4193 --------------------------------------------------------------------------*/
4194VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4195{
4196 tANI_U8 *inPtr = pValue;
4197 int tempInt;
4198 int j = 0;
4199 int v = 0;
4200 char buf[32];
4201
4202 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4203 /*no argument after the command*/
4204 if (NULL == inPtr)
4205 {
4206 return -EINVAL;
4207 }
4208
4209 /*no space after the command*/
4210 else if (SPACE_ASCII_VALUE != *inPtr)
4211 {
4212 return -EINVAL;
4213 }
4214
4215 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004216 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004217
4218 /*no argument followed by spaces*/
4219 if ('\0' == *inPtr)
4220 {
4221 return -EINVAL;
4222 }
4223
4224 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004225 v = sscanf(inPtr, "%32s ", buf);
4226 if (1 != v) return -EINVAL;
4227
Srinivas Girigowdade697412013-02-14 16:31:48 -08004228 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004229 if ((v < 0) ||
4230 (tempInt <= 0) ||
4231 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4232 {
4233 return -EINVAL;
4234 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004235
4236 *pNumChannels = tempInt;
4237
4238 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4239 "Number of channels are: %d", *pNumChannels);
4240
4241 for (j = 0; j < (*pNumChannels); j++)
4242 {
4243 /*inPtr pointing to the beginning of first space after number of channels*/
4244 inPtr = strpbrk( inPtr, " " );
4245 /*no channel list after the number of channels argument*/
4246 if (NULL == inPtr)
4247 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004248 if (0 != j)
4249 {
4250 *pNumChannels = j;
4251 return VOS_STATUS_SUCCESS;
4252 }
4253 else
4254 {
4255 return -EINVAL;
4256 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004257 }
4258
4259 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004260 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004261
4262 /*no channel list after the number of channels argument and spaces*/
4263 if ( '\0' == *inPtr )
4264 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004265 if (0 != j)
4266 {
4267 *pNumChannels = j;
4268 return VOS_STATUS_SUCCESS;
4269 }
4270 else
4271 {
4272 return -EINVAL;
4273 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004274 }
4275
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004276 v = sscanf(inPtr, "%32s ", buf);
4277 if (1 != v) return -EINVAL;
4278
Srinivas Girigowdade697412013-02-14 16:31:48 -08004279 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004280 if ((v < 0) ||
4281 (tempInt <= 0) ||
4282 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4283 {
4284 return -EINVAL;
4285 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004286 pChannelList[j] = tempInt;
4287
4288 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4289 "Channel %d added to preferred channel list",
4290 pChannelList[j] );
4291 }
4292
Srinivas Girigowdade697412013-02-14 16:31:48 -08004293 return VOS_STATUS_SUCCESS;
4294}
4295
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004296
4297/**---------------------------------------------------------------------------
4298
4299 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4300
4301 This function parses the reasoc command data passed in the format
4302 REASSOC<space><bssid><space><channel>
4303
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004304 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004305 \param - pTargetApBssid Pointer to target Ap bssid
4306 \param - pChannel Pointer to the Target AP channel
4307
4308 \return - 0 for success non-zero for failure
4309
4310 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004311VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4312 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004313{
4314 tANI_U8 *inPtr = pValue;
4315 int tempInt;
4316 int v = 0;
4317 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004318 /* 12 hexa decimal digits and 5 ':' */
4319 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004320
4321 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4322 /*no argument after the command*/
4323 if (NULL == inPtr)
4324 {
4325 return -EINVAL;
4326 }
4327
4328 /*no space after the command*/
4329 else if (SPACE_ASCII_VALUE != *inPtr)
4330 {
4331 return -EINVAL;
4332 }
4333
4334 /*removing empty spaces*/
4335 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4336
4337 /*no argument followed by spaces*/
4338 if ('\0' == *inPtr)
4339 {
4340 return -EINVAL;
4341 }
4342
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004343 v = sscanf(inPtr, "%17s", macAddress);
4344 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004345 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4347 "Invalid MAC address or All hex inputs are not read (%d)", v);
4348 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004349 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004350
4351 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4352 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4353 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4354 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4355 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4356 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004357
4358 /* point to the next argument */
4359 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4360 /*no argument after the command*/
4361 if (NULL == inPtr) return -EINVAL;
4362
4363 /*removing empty spaces*/
4364 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4365
4366 /*no argument followed by spaces*/
4367 if ('\0' == *inPtr)
4368 {
4369 return -EINVAL;
4370 }
4371
4372 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004373 v = sscanf(inPtr, "%32s ", tempBuf);
4374 if (1 != v) return -EINVAL;
4375
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004376 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004377 if ((v < 0) ||
4378 (tempInt <= 0) ||
4379 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4380 {
4381 return -EINVAL;
4382 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004383
4384 *pChannel = tempInt;
4385 return VOS_STATUS_SUCCESS;
4386}
4387
4388#endif
4389
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004390#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4391/**---------------------------------------------------------------------------
4392
4393 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4394
4395 This function parses the SETCCKM IE command
4396 SETCCKMIE<space><ie data>
4397
4398 \param - pValue Pointer to input data
4399 \param - pCckmIe Pointer to output cckm Ie
4400 \param - pCckmIeLen Pointer to output cckm ie length
4401
4402 \return - 0 for success non-zero for failure
4403
4404 --------------------------------------------------------------------------*/
4405VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4406 tANI_U8 *pCckmIeLen)
4407{
4408 tANI_U8 *inPtr = pValue;
4409 tANI_U8 *dataEnd;
4410 int j = 0;
4411 int i = 0;
4412 tANI_U8 tempByte = 0;
4413
4414 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4415 /*no argument after the command*/
4416 if (NULL == inPtr)
4417 {
4418 return -EINVAL;
4419 }
4420
4421 /*no space after the command*/
4422 else if (SPACE_ASCII_VALUE != *inPtr)
4423 {
4424 return -EINVAL;
4425 }
4426
4427 /*removing empty spaces*/
4428 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4429
4430 /*no argument followed by spaces*/
4431 if ('\0' == *inPtr)
4432 {
4433 return -EINVAL;
4434 }
4435
4436 /* find the length of data */
4437 dataEnd = inPtr;
4438 while(('\0' != *dataEnd) )
4439 {
4440 dataEnd++;
4441 ++(*pCckmIeLen);
4442 }
4443 if ( *pCckmIeLen <= 0) return -EINVAL;
4444
4445 /* Allocate the number of bytes based on the number of input characters
4446 whether it is even or odd.
4447 if the number of input characters are even, then we need N/2 byte.
4448 if the number of input characters are odd, then we need do (N+1)/2 to
4449 compensate rounding off.
4450 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4451 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4452 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4453 if (NULL == *pCckmIe)
4454 {
4455 hddLog(VOS_TRACE_LEVEL_FATAL,
4456 "%s: vos_mem_alloc failed ", __func__);
4457 return -EINVAL;
4458 }
4459 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4460 /* the buffer received from the upper layer is character buffer,
4461 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4462 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4463 and f0 in 3rd location */
4464 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4465 {
4466 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4467 (*pCckmIe)[i++] = tempByte;
4468 }
4469 *pCckmIeLen = i;
4470
4471 return VOS_STATUS_SUCCESS;
4472}
4473#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4474
Jeff Johnson295189b2012-06-20 16:38:30 -07004475/**---------------------------------------------------------------------------
4476
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004477 \brief hdd_is_valid_mac_address() - Validate MAC address
4478
4479 This function validates whether the given MAC address is valid or not
4480 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4481 where X is the hexa decimal digit character and separated by ':'
4482 This algorithm works even if MAC address is not separated by ':'
4483
4484 This code checks given input string mac contains exactly 12 hexadecimal digits.
4485 and a separator colon : appears in the input string only after
4486 an even number of hex digits.
4487
4488 \param - pMacAddr pointer to the input MAC address
4489 \return - 1 for valid and 0 for invalid
4490
4491 --------------------------------------------------------------------------*/
4492
4493v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4494{
4495 int xdigit = 0;
4496 int separator = 0;
4497 while (*pMacAddr)
4498 {
4499 if (isxdigit(*pMacAddr))
4500 {
4501 xdigit++;
4502 }
4503 else if (':' == *pMacAddr)
4504 {
4505 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4506 break;
4507
4508 ++separator;
4509 }
4510 else
4511 {
4512 separator = -1;
4513 /* Invalid MAC found */
4514 return 0;
4515 }
4516 ++pMacAddr;
4517 }
4518 return (xdigit == 12 && (separator == 5 || separator == 0));
4519}
4520
4521/**---------------------------------------------------------------------------
4522
Jeff Johnson295189b2012-06-20 16:38:30 -07004523 \brief hdd_open() - HDD Open function
4524
4525 This is called in response to ifconfig up
4526
4527 \param - dev Pointer to net_device structure
4528
4529 \return - 0 for success non-zero for failure
4530
4531 --------------------------------------------------------------------------*/
4532int hdd_open (struct net_device *dev)
4533{
4534 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4535 hdd_context_t *pHddCtx;
4536 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4537 VOS_STATUS status;
4538 v_BOOL_t in_standby = TRUE;
4539
4540 if (NULL == pAdapter)
4541 {
4542 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004543 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004544 return -ENODEV;
4545 }
4546
4547 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4548 if (NULL == pHddCtx)
4549 {
4550 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004551 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004552 return -ENODEV;
4553 }
4554
4555 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4556 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4557 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004558 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4559 {
4560 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304561 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004562 in_standby = FALSE;
4563 break;
4564 }
4565 else
4566 {
4567 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4568 pAdapterNode = pNext;
4569 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004570 }
4571
4572 if (TRUE == in_standby)
4573 {
4574 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4575 {
4576 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4577 "wlan out of power save", __func__);
4578 return -EINVAL;
4579 }
4580 }
4581
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004582 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004583 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4584 {
4585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004586 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004587 /* Enable TX queues only when we are connected */
4588 netif_tx_start_all_queues(dev);
4589 }
4590
4591 return 0;
4592}
4593
4594int hdd_mon_open (struct net_device *dev)
4595{
4596 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4597
4598 if(pAdapter == NULL) {
4599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004600 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004601 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004602 }
4603
4604 netif_start_queue(dev);
4605
4606 return 0;
4607}
4608/**---------------------------------------------------------------------------
4609
4610 \brief hdd_stop() - HDD stop function
4611
4612 This is called in response to ifconfig down
4613
4614 \param - dev Pointer to net_device structure
4615
4616 \return - 0 for success non-zero for failure
4617
4618 --------------------------------------------------------------------------*/
4619
4620int hdd_stop (struct net_device *dev)
4621{
4622 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4623 hdd_context_t *pHddCtx;
4624 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4625 VOS_STATUS status;
4626 v_BOOL_t enter_standby = TRUE;
4627
4628 ENTER();
4629
4630 if (NULL == pAdapter)
4631 {
4632 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004633 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004634 return -ENODEV;
4635 }
4636
4637 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4638 if (NULL == pHddCtx)
4639 {
4640 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004641 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004642 return -ENODEV;
4643 }
4644
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004645 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004646 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4647 netif_tx_disable(pAdapter->dev);
4648 netif_carrier_off(pAdapter->dev);
4649
4650
4651 /* SoftAP ifaces should never go in power save mode
4652 making sure same here. */
4653 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4654 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004655 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004656 )
4657 {
4658 /* SoftAP mode, so return from here */
4659 EXIT();
4660 return 0;
4661 }
4662
4663 /* Find if any iface is up then
4664 if any iface is up then can't put device to sleep/ power save mode. */
4665 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4666 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4667 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004668 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4669 {
4670 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304671 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004672 enter_standby = FALSE;
4673 break;
4674 }
4675 else
4676 {
4677 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4678 pAdapterNode = pNext;
4679 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004680 }
4681
4682 if (TRUE == enter_standby)
4683 {
4684 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4685 "entering standby", __func__);
4686 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4687 {
4688 /*log and return success*/
4689 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4690 "wlan in power save", __func__);
4691 }
4692 }
4693
4694 EXIT();
4695 return 0;
4696}
4697
4698/**---------------------------------------------------------------------------
4699
4700 \brief hdd_uninit() - HDD uninit function
4701
4702 This is called during the netdev unregister to uninitialize all data
4703associated with the device
4704
4705 \param - dev Pointer to net_device structure
4706
4707 \return - void
4708
4709 --------------------------------------------------------------------------*/
4710static void hdd_uninit (struct net_device *dev)
4711{
4712 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4713
4714 ENTER();
4715
4716 do
4717 {
4718 if (NULL == pAdapter)
4719 {
4720 hddLog(VOS_TRACE_LEVEL_FATAL,
4721 "%s: NULL pAdapter", __func__);
4722 break;
4723 }
4724
4725 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4726 {
4727 hddLog(VOS_TRACE_LEVEL_FATAL,
4728 "%s: Invalid magic", __func__);
4729 break;
4730 }
4731
4732 if (NULL == pAdapter->pHddCtx)
4733 {
4734 hddLog(VOS_TRACE_LEVEL_FATAL,
4735 "%s: NULL pHddCtx", __func__);
4736 break;
4737 }
4738
4739 if (dev != pAdapter->dev)
4740 {
4741 hddLog(VOS_TRACE_LEVEL_FATAL,
4742 "%s: Invalid device reference", __func__);
4743 /* we haven't validated all cases so let this go for now */
4744 }
4745
4746 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4747
4748 /* after uninit our adapter structure will no longer be valid */
4749 pAdapter->dev = NULL;
4750 pAdapter->magic = 0;
4751 } while (0);
4752
4753 EXIT();
4754}
4755
4756/**---------------------------------------------------------------------------
4757
4758 \brief hdd_release_firmware() -
4759
4760 This function calls the release firmware API to free the firmware buffer.
4761
4762 \param - pFileName Pointer to the File Name.
4763 pCtx - Pointer to the adapter .
4764
4765
4766 \return - 0 for success, non zero for failure
4767
4768 --------------------------------------------------------------------------*/
4769
4770VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4771{
4772 VOS_STATUS status = VOS_STATUS_SUCCESS;
4773 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4774 ENTER();
4775
4776
4777 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4778
4779 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4780
4781 if(pHddCtx->fw) {
4782 release_firmware(pHddCtx->fw);
4783 pHddCtx->fw = NULL;
4784 }
4785 else
4786 status = VOS_STATUS_E_FAILURE;
4787 }
4788 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4789 if(pHddCtx->nv) {
4790 release_firmware(pHddCtx->nv);
4791 pHddCtx->nv = NULL;
4792 }
4793 else
4794 status = VOS_STATUS_E_FAILURE;
4795
4796 }
4797
4798 EXIT();
4799 return status;
4800}
4801
4802/**---------------------------------------------------------------------------
4803
4804 \brief hdd_request_firmware() -
4805
4806 This function reads the firmware file using the request firmware
4807 API and returns the the firmware data and the firmware file size.
4808
4809 \param - pfileName - Pointer to the file name.
4810 - pCtx - Pointer to the adapter .
4811 - ppfw_data - Pointer to the pointer of the firmware data.
4812 - pSize - Pointer to the file size.
4813
4814 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4815
4816 --------------------------------------------------------------------------*/
4817
4818
4819VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4820{
4821 int status;
4822 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4823 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4824 ENTER();
4825
4826 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4827
4828 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4829
4830 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4831 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4832 __func__, pfileName);
4833 retval = VOS_STATUS_E_FAILURE;
4834 }
4835
4836 else {
4837 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4838 *pSize = pHddCtx->fw->size;
4839 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4840 __func__, *pSize);
4841 }
4842 }
4843 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4844
4845 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4846
4847 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4848 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4849 __func__, pfileName);
4850 retval = VOS_STATUS_E_FAILURE;
4851 }
4852
4853 else {
4854 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4855 *pSize = pHddCtx->nv->size;
4856 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4857 __func__, *pSize);
4858 }
4859 }
4860
4861 EXIT();
4862 return retval;
4863}
4864/**---------------------------------------------------------------------------
4865 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4866
4867 This is the function invoked by SME to inform the result of a full power
4868 request issued by HDD
4869
4870 \param - callbackcontext - Pointer to cookie
4871 status - result of request
4872
4873 \return - None
4874
4875--------------------------------------------------------------------------*/
4876void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4877{
4878 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4879
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004880 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004881 if(&pHddCtx->full_pwr_comp_var)
4882 {
4883 complete(&pHddCtx->full_pwr_comp_var);
4884 }
4885}
4886
4887/**---------------------------------------------------------------------------
4888
4889 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4890
4891 This is the function invoked by SME to inform the result of BMPS
4892 request issued by HDD
4893
4894 \param - callbackcontext - Pointer to cookie
4895 status - result of request
4896
4897 \return - None
4898
4899--------------------------------------------------------------------------*/
4900void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4901{
4902
4903 struct completion *completion_var = (struct completion*) callbackContext;
4904
4905 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d\n", status);
4906 if(completion_var != NULL)
4907 {
4908 complete(completion_var);
4909 }
4910}
4911
4912/**---------------------------------------------------------------------------
4913
4914 \brief hdd_get_cfg_file_size() -
4915
4916 This function reads the configuration file using the request firmware
4917 API and returns the configuration file size.
4918
4919 \param - pCtx - Pointer to the adapter .
4920 - pFileName - Pointer to the file name.
4921 - pBufSize - Pointer to the buffer size.
4922
4923 \return - 0 for success, non zero for failure
4924
4925 --------------------------------------------------------------------------*/
4926
4927VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4928{
4929 int status;
4930 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4931
4932 ENTER();
4933
4934 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4935
4936 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4937 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4938 status = VOS_STATUS_E_FAILURE;
4939 }
4940 else {
4941 *pBufSize = pHddCtx->fw->size;
4942 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4943 release_firmware(pHddCtx->fw);
4944 pHddCtx->fw = NULL;
4945 }
4946
4947 EXIT();
4948 return VOS_STATUS_SUCCESS;
4949}
4950
4951/**---------------------------------------------------------------------------
4952
4953 \brief hdd_read_cfg_file() -
4954
4955 This function reads the configuration file using the request firmware
4956 API and returns the cfg data and the buffer size of the configuration file.
4957
4958 \param - pCtx - Pointer to the adapter .
4959 - pFileName - Pointer to the file name.
4960 - pBuffer - Pointer to the data buffer.
4961 - pBufSize - Pointer to the buffer size.
4962
4963 \return - 0 for success, non zero for failure
4964
4965 --------------------------------------------------------------------------*/
4966
4967VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4968 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4969{
4970 int status;
4971 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4972
4973 ENTER();
4974
4975 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4976
4977 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4978 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4979 return VOS_STATUS_E_FAILURE;
4980 }
4981 else {
4982 if(*pBufSize != pHddCtx->fw->size) {
4983 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4984 "file size", __func__);
4985 release_firmware(pHddCtx->fw);
4986 pHddCtx->fw = NULL;
4987 return VOS_STATUS_E_FAILURE;
4988 }
4989 else {
4990 if(pBuffer) {
4991 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4992 }
4993 release_firmware(pHddCtx->fw);
4994 pHddCtx->fw = NULL;
4995 }
4996 }
4997
4998 EXIT();
4999
5000 return VOS_STATUS_SUCCESS;
5001}
5002
5003/**---------------------------------------------------------------------------
5004
Jeff Johnson295189b2012-06-20 16:38:30 -07005005 \brief hdd_set_mac_address() -
5006
5007 This function sets the user specified mac address using
5008 the command ifconfig wlanX hw ether <mac adress>.
5009
5010 \param - dev - Pointer to the net device.
5011 - addr - Pointer to the sockaddr.
5012 \return - 0 for success, non zero for failure
5013
5014 --------------------------------------------------------------------------*/
5015
5016static int hdd_set_mac_address(struct net_device *dev, void *addr)
5017{
5018 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5019 struct sockaddr *psta_mac_addr = addr;
5020 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5021
5022 ENTER();
5023
5024 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5025
5026#ifdef HDD_SESSIONIZE
5027 // set the MAC address though the STA ID CFG.
5028 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5029 (v_U8_t *)&pAdapter->macAddressCurrent,
5030 sizeof( pAdapter->macAddressCurrent ),
5031 hdd_set_mac_addr_cb, VOS_FALSE );
5032#endif
5033
5034 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5035
5036 EXIT();
5037 return halStatus;
5038}
5039
5040tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5041{
5042 int i;
5043 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5044 {
5045 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5046 break;
5047 }
5048
5049 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5050 return NULL;
5051
5052 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5053 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5054}
5055
5056void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5057{
5058 int i;
5059 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5060 {
5061 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5062 {
5063 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5064 break;
5065 }
5066 }
5067 return;
5068}
5069
5070#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5071 static struct net_device_ops wlan_drv_ops = {
5072 .ndo_open = hdd_open,
5073 .ndo_stop = hdd_stop,
5074 .ndo_uninit = hdd_uninit,
5075 .ndo_start_xmit = hdd_hard_start_xmit,
5076 .ndo_tx_timeout = hdd_tx_timeout,
5077 .ndo_get_stats = hdd_stats,
5078 .ndo_do_ioctl = hdd_ioctl,
5079 .ndo_set_mac_address = hdd_set_mac_address,
5080 .ndo_select_queue = hdd_select_queue,
5081#ifdef WLAN_FEATURE_PACKET_FILTERING
5082#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5083 .ndo_set_rx_mode = hdd_set_multicast_list,
5084#else
5085 .ndo_set_multicast_list = hdd_set_multicast_list,
5086#endif //LINUX_VERSION_CODE
5087#endif
5088 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005089 static struct net_device_ops wlan_mon_drv_ops = {
5090 .ndo_open = hdd_mon_open,
5091 .ndo_stop = hdd_stop,
5092 .ndo_uninit = hdd_uninit,
5093 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5094 .ndo_tx_timeout = hdd_tx_timeout,
5095 .ndo_get_stats = hdd_stats,
5096 .ndo_do_ioctl = hdd_ioctl,
5097 .ndo_set_mac_address = hdd_set_mac_address,
5098 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005099
5100#endif
5101
5102void hdd_set_station_ops( struct net_device *pWlanDev )
5103{
5104#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005105 pWlanDev->netdev_ops = &wlan_drv_ops;
5106#else
5107 pWlanDev->open = hdd_open;
5108 pWlanDev->stop = hdd_stop;
5109 pWlanDev->uninit = hdd_uninit;
5110 pWlanDev->hard_start_xmit = NULL;
5111 pWlanDev->tx_timeout = hdd_tx_timeout;
5112 pWlanDev->get_stats = hdd_stats;
5113 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005114 pWlanDev->set_mac_address = hdd_set_mac_address;
5115#endif
5116}
5117
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005118static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005119{
5120 struct net_device *pWlanDev = NULL;
5121 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005122 /*
5123 * cfg80211 initialization and registration....
5124 */
5125 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5126
Jeff Johnson295189b2012-06-20 16:38:30 -07005127 if(pWlanDev != NULL)
5128 {
5129
5130 //Save the pointer to the net_device in the HDD adapter
5131 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5132
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5134
5135 pAdapter->dev = pWlanDev;
5136 pAdapter->pHddCtx = pHddCtx;
5137 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5138
5139 init_completion(&pAdapter->session_open_comp_var);
5140 init_completion(&pAdapter->session_close_comp_var);
5141 init_completion(&pAdapter->disconnect_comp_var);
5142 init_completion(&pAdapter->linkup_event_var);
5143 init_completion(&pAdapter->cancel_rem_on_chan_var);
5144 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005145#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5146 init_completion(&pAdapter->offchannel_tx_event);
5147#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005148 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005149#ifdef FEATURE_WLAN_TDLS
5150 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005151 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005152 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305153 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005154#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005155 init_completion(&pHddCtx->mc_sus_event_var);
5156 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305157 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005158 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005159 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005160
Rajeev79dbe4c2013-10-05 11:03:42 +05305161#ifdef FEATURE_WLAN_BATCH_SCAN
5162 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5163 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5164 pAdapter->pBatchScanRsp = NULL;
5165 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005166 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08005167 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305168 mutex_init(&pAdapter->hdd_batch_scan_lock);
5169#endif
5170
Jeff Johnson295189b2012-06-20 16:38:30 -07005171 pAdapter->isLinkUpSvcNeeded = FALSE;
5172 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5173 //Init the net_device structure
5174 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5175
5176 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5177 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5178 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5179 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5180
5181 hdd_set_station_ops( pAdapter->dev );
5182
5183 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005184 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5185 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5186 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005187 /* set pWlanDev's parent to underlying device */
5188 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5189 }
5190
5191 return pAdapter;
5192}
5193
5194VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5195{
5196 struct net_device *pWlanDev = pAdapter->dev;
5197 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5198 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5199 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5200
5201 if( rtnl_lock_held )
5202 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005203 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005204 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5205 {
5206 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5207 return VOS_STATUS_E_FAILURE;
5208 }
5209 }
5210 if (register_netdevice(pWlanDev))
5211 {
5212 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5213 return VOS_STATUS_E_FAILURE;
5214 }
5215 }
5216 else
5217 {
5218 if(register_netdev(pWlanDev))
5219 {
5220 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5221 return VOS_STATUS_E_FAILURE;
5222 }
5223 }
5224 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5225
5226 return VOS_STATUS_SUCCESS;
5227}
5228
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005229static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005230{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005231 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005232
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005233 if (NULL == pAdapter)
5234 {
5235 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5236 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005237 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005238
5239 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5240 {
5241 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5242 return eHAL_STATUS_NOT_INITIALIZED;
5243 }
5244
5245 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5246
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005247#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005248 /* need to make sure all of our scheduled work has completed.
5249 * This callback is called from MC thread context, so it is safe to
5250 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005251 *
5252 * Even though this is called from MC thread context, if there is a faulty
5253 * work item in the system, that can hang this call forever. So flushing
5254 * this global work queue is not safe; and now we make sure that
5255 * individual work queues are stopped correctly. But the cancel work queue
5256 * is a GPL only API, so the proprietary version of the driver would still
5257 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005258 */
5259 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005260#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005261
5262 /* We can be blocked while waiting for scheduled work to be
5263 * flushed, and the adapter structure can potentially be freed, in
5264 * which case the magic will have been reset. So make sure the
5265 * magic is still good, and hence the adapter structure is still
5266 * valid, before signaling completion */
5267 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5268 {
5269 complete(&pAdapter->session_close_comp_var);
5270 }
5271
Jeff Johnson295189b2012-06-20 16:38:30 -07005272 return eHAL_STATUS_SUCCESS;
5273}
5274
5275VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5276{
5277 struct net_device *pWlanDev = pAdapter->dev;
5278 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5279 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5280 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5281 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5282 int rc = 0;
5283
5284 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005285 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005286 //Open a SME session for future operation
5287 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005288 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005289 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5290 {
5291 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005292 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005293 halStatus, halStatus );
5294 status = VOS_STATUS_E_FAILURE;
5295 goto error_sme_open;
5296 }
5297
5298 //Block on a completion variable. Can't wait forever though.
5299 rc = wait_for_completion_interruptible_timeout(
5300 &pAdapter->session_open_comp_var,
5301 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5302 if (!rc)
5303 {
5304 hddLog(VOS_TRACE_LEVEL_FATAL,
5305 "Session is not opened within timeout period code %08d", rc );
5306 status = VOS_STATUS_E_FAILURE;
5307 goto error_sme_open;
5308 }
5309
5310 // Register wireless extensions
5311 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5312 {
5313 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005314 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005315 halStatus, halStatus );
5316 status = VOS_STATUS_E_FAILURE;
5317 goto error_register_wext;
5318 }
5319 //Safe to register the hard_start_xmit function again
5320#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5321 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5322#else
5323 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5324#endif
5325
5326 //Set the Connection State to Not Connected
5327 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5328
5329 //Set the default operation channel
5330 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5331
5332 /* Make the default Auth Type as OPEN*/
5333 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5334
5335 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5336 {
5337 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005338 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005339 status, status );
5340 goto error_init_txrx;
5341 }
5342
5343 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5344
5345 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5346 {
5347 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005348 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005349 status, status );
5350 goto error_wmm_init;
5351 }
5352
5353 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5354
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005355#ifdef FEATURE_WLAN_TDLS
5356 if(0 != wlan_hdd_tdls_init(pAdapter))
5357 {
5358 status = VOS_STATUS_E_FAILURE;
5359 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5360 goto error_tdls_init;
5361 }
5362 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5363#endif
5364
Jeff Johnson295189b2012-06-20 16:38:30 -07005365 return VOS_STATUS_SUCCESS;
5366
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005367#ifdef FEATURE_WLAN_TDLS
5368error_tdls_init:
5369 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5370 hdd_wmm_adapter_close(pAdapter);
5371#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005372error_wmm_init:
5373 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5374 hdd_deinit_tx_rx(pAdapter);
5375error_init_txrx:
5376 hdd_UnregisterWext(pWlanDev);
5377error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005378 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005379 {
5380 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005381 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005382 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005383 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005384 {
5385 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005386 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005387 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005388 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005389 }
5390}
5391error_sme_open:
5392 return status;
5393}
5394
Jeff Johnson295189b2012-06-20 16:38:30 -07005395void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5396{
5397 hdd_cfg80211_state_t *cfgState;
5398
5399 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5400
5401 if( NULL != cfgState->buf )
5402 {
5403 int rc;
5404 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5405 rc = wait_for_completion_interruptible_timeout(
5406 &pAdapter->tx_action_cnf_event,
5407 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5408 if(!rc)
5409 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005410 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07005411 ("ERROR: HDD Wait for Action Confirmation Failed!!\n"));
5412 }
5413 }
5414 return;
5415}
Jeff Johnson295189b2012-06-20 16:38:30 -07005416
5417void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5418{
5419 ENTER();
5420 switch ( pAdapter->device_mode )
5421 {
5422 case WLAN_HDD_INFRA_STATION:
5423 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005424 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005425 {
5426 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5427 {
5428 hdd_deinit_tx_rx( pAdapter );
5429 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5430 }
5431
5432 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5433 {
5434 hdd_wmm_adapter_close( pAdapter );
5435 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5436 }
5437
Jeff Johnson295189b2012-06-20 16:38:30 -07005438 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005439#ifdef FEATURE_WLAN_TDLS
5440 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5441 {
5442 wlan_hdd_tdls_exit(pAdapter);
5443 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5444 }
5445#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005446
5447 break;
5448 }
5449
5450 case WLAN_HDD_SOFTAP:
5451 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005452 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305453
5454 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5455 {
5456 hdd_wmm_adapter_close( pAdapter );
5457 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5458 }
5459
Jeff Johnson295189b2012-06-20 16:38:30 -07005460 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005461
5462 hdd_unregister_hostapd(pAdapter);
5463 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005464 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005465 break;
5466 }
5467
5468 case WLAN_HDD_MONITOR:
5469 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005470 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005471 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5472 {
5473 hdd_deinit_tx_rx( pAdapter );
5474 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5475 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005476 if(NULL != pAdapterforTx)
5477 {
5478 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5479 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005480 break;
5481 }
5482
5483
5484 default:
5485 break;
5486 }
5487
5488 EXIT();
5489}
5490
5491void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5492{
5493 struct net_device *pWlanDev = pAdapter->dev;
5494
Rajeev79dbe4c2013-10-05 11:03:42 +05305495#ifdef FEATURE_WLAN_BATCH_SCAN
5496 tHddBatchScanRsp *pNode;
5497 tHddBatchScanRsp *pPrev;
5498 if (pAdapter)
5499 {
5500 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5501 pNode = pAdapter->pBatchScanRsp;
5502 while (pNode)
5503 {
5504 pPrev = pNode;
5505 pNode = pNode->pNext;
5506 vos_mem_free((v_VOID_t * )pPrev);
5507 }
5508 pAdapter->pBatchScanRsp = NULL;
5509 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5510 }
5511#endif
5512
Jeff Johnson295189b2012-06-20 16:38:30 -07005513 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5514 if( rtnl_held )
5515 {
5516 unregister_netdevice(pWlanDev);
5517 }
5518 else
5519 {
5520 unregister_netdev(pWlanDev);
5521 }
5522 // note that the pAdapter is no longer valid at this point
5523 // since the memory has been reclaimed
5524 }
5525
5526}
5527
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005528void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5529{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305530 VOS_STATUS status;
5531 hdd_adapter_t *pAdapter = NULL;
5532 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005533
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305534 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005535
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305536 /*loop through all adapters.*/
5537 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005538 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305539 pAdapter = pAdapterNode->pAdapter;
5540 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5541 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005542
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305543 { // we skip this registration for modes other than STA and P2P client modes.
5544 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5545 pAdapterNode = pNext;
5546 continue;
5547 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005548
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305549 //Apply Dynamic DTIM For P2P
5550 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5551 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5552 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5553 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5554 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5555 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5556 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5557 (eConnectionState_Associated ==
5558 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5559 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5560 {
5561 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005562
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305563 powerRequest.uIgnoreDTIM = 1;
5564 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5565
5566 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5567 {
5568 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5569 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5570 }
5571 else
5572 {
5573 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5574 }
5575
5576 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5577 * specified during Enter/Exit BMPS when LCD off*/
5578 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5579 NULL, eANI_BOOLEAN_FALSE);
5580 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5581 NULL, eANI_BOOLEAN_FALSE);
5582
5583 /* switch to the DTIM specified in cfg.ini */
5584 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5585 "Switch to DTIM %d", powerRequest.uListenInterval);
5586 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5587 break;
5588
5589 }
5590
5591 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5592 pAdapterNode = pNext;
5593 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005594}
5595
5596void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5597{
5598 /*Switch back to DTIM 1*/
5599 tSirSetPowerParamsReq powerRequest = { 0 };
5600
5601 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5602 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005603 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005604
5605 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5606 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5607 NULL, eANI_BOOLEAN_FALSE);
5608 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5609 NULL, eANI_BOOLEAN_FALSE);
5610
5611 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5612 "Switch to DTIM%d",powerRequest.uListenInterval);
5613 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5614
5615}
5616
Jeff Johnson295189b2012-06-20 16:38:30 -07005617VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5618{
5619 VOS_STATUS status = VOS_STATUS_SUCCESS;
5620
5621 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5622 {
5623 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5624 }
5625
5626 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5627 {
5628 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5629 }
5630
5631 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5632 {
5633 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5634 }
5635
5636 return status;
5637}
5638
5639VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5640{
5641 hdd_adapter_t *pAdapter = NULL;
5642 eHalStatus halStatus;
5643 VOS_STATUS status = VOS_STATUS_E_INVAL;
5644 v_BOOL_t disableBmps = FALSE;
5645 v_BOOL_t disableImps = FALSE;
5646
5647 switch(session_type)
5648 {
5649 case WLAN_HDD_INFRA_STATION:
5650 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005651 case WLAN_HDD_P2P_CLIENT:
5652 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005653 //Exit BMPS -> Is Sta/P2P Client is already connected
5654 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5655 if((NULL != pAdapter)&&
5656 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5657 {
5658 disableBmps = TRUE;
5659 }
5660
5661 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5662 if((NULL != pAdapter)&&
5663 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5664 {
5665 disableBmps = TRUE;
5666 }
5667
5668 //Exit both Bmps and Imps incase of Go/SAP Mode
5669 if((WLAN_HDD_SOFTAP == session_type) ||
5670 (WLAN_HDD_P2P_GO == session_type))
5671 {
5672 disableBmps = TRUE;
5673 disableImps = TRUE;
5674 }
5675
5676 if(TRUE == disableImps)
5677 {
5678 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5679 {
5680 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5681 }
5682 }
5683
5684 if(TRUE == disableBmps)
5685 {
5686 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5687 {
5688 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5689
5690 if(eHAL_STATUS_SUCCESS != halStatus)
5691 {
5692 status = VOS_STATUS_E_FAILURE;
5693 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save\n", __func__);
5694 VOS_ASSERT(0);
5695 return status;
5696 }
5697 }
5698
5699 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5700 {
5701 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5702
5703 if(eHAL_STATUS_SUCCESS != halStatus)
5704 {
5705 status = VOS_STATUS_E_FAILURE;
5706 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer\n", __func__);
5707 VOS_ASSERT(0);
5708 return status;
5709 }
5710 }
5711 }
5712
5713 if((TRUE == disableBmps) ||
5714 (TRUE == disableImps))
5715 {
5716 /* Now, get the chip into Full Power now */
5717 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5718 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5719 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5720
5721 if(halStatus != eHAL_STATUS_SUCCESS)
5722 {
5723 if(halStatus == eHAL_STATUS_PMC_PENDING)
5724 {
5725 //Block on a completion variable. Can't wait forever though
5726 wait_for_completion_interruptible_timeout(
5727 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5728 }
5729 else
5730 {
5731 status = VOS_STATUS_E_FAILURE;
5732 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed\n", __func__);
5733 VOS_ASSERT(0);
5734 return status;
5735 }
5736 }
5737
5738 status = VOS_STATUS_SUCCESS;
5739 }
5740
5741 break;
5742 }
5743 return status;
5744}
5745
5746hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005747 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005748 tANI_U8 rtnl_held )
5749{
5750 hdd_adapter_t *pAdapter = NULL;
5751 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5752 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5753 VOS_STATUS exitbmpsStatus;
5754
5755 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d\n",__func__,iface_name,session_type);
5756
5757 //Disable BMPS incase of Concurrency
5758 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5759
5760 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5761 {
5762 //Fail to Exit BMPS
5763 VOS_ASSERT(0);
5764 return NULL;
5765 }
5766
5767 switch(session_type)
5768 {
5769 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005770 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005771 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005772 {
5773 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5774
5775 if( NULL == pAdapter )
5776 return NULL;
5777
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305778#ifdef FEATURE_WLAN_TDLS
5779 /* A Mutex Lock is introduced while changing/initializing the mode to
5780 * protect the concurrent access for the Adapters by TDLS module.
5781 */
5782 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5783 {
5784 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5785 "%s: unable to lock list", __func__);
5786 return NULL;
5787 }
5788#endif
5789
Jeff Johnsone7245742012-09-05 17:12:55 -07005790 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5791 NL80211_IFTYPE_P2P_CLIENT:
5792 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005793
Jeff Johnson295189b2012-06-20 16:38:30 -07005794 pAdapter->device_mode = session_type;
5795
5796 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305797#ifdef FEATURE_WLAN_TDLS
5798 mutex_unlock(&pHddCtx->tdls_lock);
5799#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005800 if( VOS_STATUS_SUCCESS != status )
5801 goto err_free_netdev;
5802
5803 status = hdd_register_interface( pAdapter, rtnl_held );
5804 if( VOS_STATUS_SUCCESS != status )
5805 {
5806 hdd_deinit_adapter(pHddCtx, pAdapter);
5807 goto err_free_netdev;
5808 }
5809 //Stop the Interface TX queue.
5810 netif_tx_disable(pAdapter->dev);
5811 //netif_tx_disable(pWlanDev);
5812 netif_carrier_off(pAdapter->dev);
5813
5814 break;
5815 }
5816
Jeff Johnson295189b2012-06-20 16:38:30 -07005817 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005818 case WLAN_HDD_SOFTAP:
5819 {
5820 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5821 if( NULL == pAdapter )
5822 return NULL;
5823
Jeff Johnson295189b2012-06-20 16:38:30 -07005824 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5825 NL80211_IFTYPE_AP:
5826 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 pAdapter->device_mode = session_type;
5828
5829 status = hdd_init_ap_mode(pAdapter);
5830 if( VOS_STATUS_SUCCESS != status )
5831 goto err_free_netdev;
5832
5833 status = hdd_register_hostapd( pAdapter, rtnl_held );
5834 if( VOS_STATUS_SUCCESS != status )
5835 {
5836 hdd_deinit_adapter(pHddCtx, pAdapter);
5837 goto err_free_netdev;
5838 }
5839
5840 netif_tx_disable(pAdapter->dev);
5841 netif_carrier_off(pAdapter->dev);
5842
5843 hdd_set_conparam( 1 );
5844 break;
5845 }
5846 case WLAN_HDD_MONITOR:
5847 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005848 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5849 if( NULL == pAdapter )
5850 return NULL;
5851
5852 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5853 pAdapter->device_mode = session_type;
5854 status = hdd_register_interface( pAdapter, rtnl_held );
5855#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5856 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5857#else
5858 pAdapter->dev->open = hdd_mon_open;
5859 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5860#endif
5861 hdd_init_tx_rx( pAdapter );
5862 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5863 //Set adapter to be used for data tx. It will use either GO or softap.
5864 pAdapter->sessionCtx.monitor.pAdapterForTx =
5865 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005866 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5867 {
5868 pAdapter->sessionCtx.monitor.pAdapterForTx =
5869 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5870 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005871 /* This workqueue will be used to transmit management packet over
5872 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005873 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5874 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5875 return NULL;
5876 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005877
Jeff Johnson295189b2012-06-20 16:38:30 -07005878 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5879 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005880 }
5881 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005882 case WLAN_HDD_FTM:
5883 {
5884 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5885
5886 if( NULL == pAdapter )
5887 return NULL;
5888 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5889 * message while loading driver in FTM mode. */
5890 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5891 pAdapter->device_mode = session_type;
5892 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305893
5894 hdd_init_tx_rx( pAdapter );
5895
5896 //Stop the Interface TX queue.
5897 netif_tx_disable(pAdapter->dev);
5898 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005899 }
5900 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005901 default:
5902 {
5903 VOS_ASSERT(0);
5904 return NULL;
5905 }
5906 }
5907
5908
5909 if( VOS_STATUS_SUCCESS == status )
5910 {
5911 //Add it to the hdd's session list.
5912 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5913 if( NULL == pHddAdapterNode )
5914 {
5915 status = VOS_STATUS_E_NOMEM;
5916 }
5917 else
5918 {
5919 pHddAdapterNode->pAdapter = pAdapter;
5920 status = hdd_add_adapter_back ( pHddCtx,
5921 pHddAdapterNode );
5922 }
5923 }
5924
5925 if( VOS_STATUS_SUCCESS != status )
5926 {
5927 if( NULL != pAdapter )
5928 {
5929 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5930 pAdapter = NULL;
5931 }
5932 if( NULL != pHddAdapterNode )
5933 {
5934 vos_mem_free( pHddAdapterNode );
5935 }
5936
5937 goto resume_bmps;
5938 }
5939
5940 if(VOS_STATUS_SUCCESS == status)
5941 {
5942 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5943
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005944 //Initialize the WoWL service
5945 if(!hdd_init_wowl(pAdapter))
5946 {
5947 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5948 goto err_free_netdev;
5949 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005950 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005951 return pAdapter;
5952
5953err_free_netdev:
5954 free_netdev(pAdapter->dev);
5955 wlan_hdd_release_intf_addr( pHddCtx,
5956 pAdapter->macAddressCurrent.bytes );
5957
5958resume_bmps:
5959 //If bmps disabled enable it
5960 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5961 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305962 if (pHddCtx->hdd_wlan_suspended)
5963 {
5964 hdd_set_pwrparams(pHddCtx);
5965 }
5966 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005967 }
5968 return NULL;
5969}
5970
5971VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5972 tANI_U8 rtnl_held )
5973{
5974 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5975 VOS_STATUS status;
5976
5977 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5978 if( VOS_STATUS_SUCCESS != status )
5979 return status;
5980
5981 while ( pCurrent->pAdapter != pAdapter )
5982 {
5983 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5984 if( VOS_STATUS_SUCCESS != status )
5985 break;
5986
5987 pCurrent = pNext;
5988 }
5989 pAdapterNode = pCurrent;
5990 if( VOS_STATUS_SUCCESS == status )
5991 {
5992 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5993 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305994
5995#ifdef FEATURE_WLAN_TDLS
5996
5997 /* A Mutex Lock is introduced while changing/initializing the mode to
5998 * protect the concurrent access for the Adapters by TDLS module.
5999 */
6000 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6001 {
6002 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6003 "%s: unable to lock list", __func__);
6004 return VOS_STATUS_E_FAILURE;
6005 }
6006#endif
6007
Jeff Johnson295189b2012-06-20 16:38:30 -07006008 hdd_remove_adapter( pHddCtx, pAdapterNode );
6009 vos_mem_free( pAdapterNode );
6010
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306011#ifdef FEATURE_WLAN_TDLS
6012 mutex_unlock(&pHddCtx->tdls_lock);
6013#endif
6014
Jeff Johnson295189b2012-06-20 16:38:30 -07006015
6016 /* If there is a single session of STA/P2P client, re-enable BMPS */
6017 if ((!vos_concurrent_sessions_running()) &&
6018 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6019 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6020 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306021 if (pHddCtx->hdd_wlan_suspended)
6022 {
6023 hdd_set_pwrparams(pHddCtx);
6024 }
6025 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006026 }
6027
6028 return VOS_STATUS_SUCCESS;
6029 }
6030
6031 return VOS_STATUS_E_FAILURE;
6032}
6033
6034VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6035{
6036 hdd_adapter_list_node_t *pHddAdapterNode;
6037 VOS_STATUS status;
6038
6039 ENTER();
6040
6041 do
6042 {
6043 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6044 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6045 {
6046 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6047 vos_mem_free( pHddAdapterNode );
6048 }
6049 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6050
6051 EXIT();
6052
6053 return VOS_STATUS_SUCCESS;
6054}
6055
6056void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6057{
6058 v_U8_t addIE[1] = {0};
6059
6060 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6061 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6062 eANI_BOOLEAN_FALSE) )
6063 {
6064 hddLog(LOGE,
6065 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM\n");
6066 }
6067
6068 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6069 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6070 eANI_BOOLEAN_FALSE) )
6071 {
6072 hddLog(LOGE,
6073 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM\n");
6074 }
6075
6076 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6077 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6078 eANI_BOOLEAN_FALSE) )
6079 {
6080 hddLog(LOGE,
6081 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM\n");
6082 }
6083}
6084
6085VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6086{
6087 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6088 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6089 union iwreq_data wrqu;
6090
6091 ENTER();
6092
6093 switch(pAdapter->device_mode)
6094 {
6095 case WLAN_HDD_INFRA_STATION:
6096 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006097 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006098 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6099 {
6100 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6101 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6102 pAdapter->sessionId,
6103 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6104 else
6105 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6106 pAdapter->sessionId,
6107 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6108 //success implies disconnect command got queued up successfully
6109 if(halStatus == eHAL_STATUS_SUCCESS)
6110 {
6111 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6112 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6113 }
6114 memset(&wrqu, '\0', sizeof(wrqu));
6115 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6116 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6117 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6118 }
6119 else
6120 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306121 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006122 }
6123
6124 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6125 {
6126 INIT_COMPLETION(pAdapter->session_close_comp_var);
6127 if (eHAL_STATUS_SUCCESS ==
6128 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6129 hdd_smeCloseSessionCallback, pAdapter))
6130 {
6131 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006132 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006133 &pAdapter->session_close_comp_var,
6134 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6135 }
6136 }
6137
6138 break;
6139
6140 case WLAN_HDD_SOFTAP:
6141 case WLAN_HDD_P2P_GO:
6142 //Any softap specific cleanup here...
6143 mutex_lock(&pHddCtx->sap_lock);
6144 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6145 {
6146 VOS_STATUS status;
6147 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6148
6149 //Stop Bss.
6150 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6151 if (VOS_IS_STATUS_SUCCESS(status))
6152 {
6153 hdd_hostapd_state_t *pHostapdState =
6154 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6155
6156 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6157
6158 if (!VOS_IS_STATUS_SUCCESS(status))
6159 {
6160 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006161 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006162 }
6163 }
6164 else
6165 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006166 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006167 }
6168 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6169
6170 if (eHAL_STATUS_FAILURE ==
6171 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6172 0, NULL, eANI_BOOLEAN_FALSE))
6173 {
6174 hddLog(LOGE,
6175 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006176 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006177 }
6178
6179 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6180 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6181 eANI_BOOLEAN_FALSE) )
6182 {
6183 hddLog(LOGE,
6184 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6185 }
6186
6187 // Reset WNI_CFG_PROBE_RSP Flags
6188 wlan_hdd_reset_prob_rspies(pAdapter);
6189 kfree(pAdapter->sessionCtx.ap.beacon);
6190 pAdapter->sessionCtx.ap.beacon = NULL;
6191 }
6192 mutex_unlock(&pHddCtx->sap_lock);
6193 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006194
Jeff Johnson295189b2012-06-20 16:38:30 -07006195 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006196#ifdef WLAN_OPEN_SOURCE
6197 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6198#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006199 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006200
Jeff Johnson295189b2012-06-20 16:38:30 -07006201 default:
6202 break;
6203 }
6204
6205 EXIT();
6206 return VOS_STATUS_SUCCESS;
6207}
6208
6209VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6210{
6211 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6212 VOS_STATUS status;
6213 hdd_adapter_t *pAdapter;
6214
6215 ENTER();
6216
6217 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6218
6219 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6220 {
6221 pAdapter = pAdapterNode->pAdapter;
6222 netif_tx_disable(pAdapter->dev);
6223 netif_carrier_off(pAdapter->dev);
6224
6225 hdd_stop_adapter( pHddCtx, pAdapter );
6226
6227 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6228 pAdapterNode = pNext;
6229 }
6230
6231 EXIT();
6232
6233 return VOS_STATUS_SUCCESS;
6234}
6235
6236VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6237{
6238 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6239 VOS_STATUS status;
6240 hdd_adapter_t *pAdapter;
6241
6242 ENTER();
6243
6244 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6245
6246 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6247 {
6248 pAdapter = pAdapterNode->pAdapter;
6249 netif_tx_disable(pAdapter->dev);
6250 netif_carrier_off(pAdapter->dev);
6251
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006252 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6253
Jeff Johnson295189b2012-06-20 16:38:30 -07006254 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306255 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6256 {
6257 hdd_wmm_adapter_close( pAdapter );
6258 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6259 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006260
6261 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6262 pAdapterNode = pNext;
6263 }
6264
6265 EXIT();
6266
6267 return VOS_STATUS_SUCCESS;
6268}
6269
6270VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6271{
6272 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6273 VOS_STATUS status;
6274 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306275 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006276
6277 ENTER();
6278
6279 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6280
6281 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6282 {
6283 pAdapter = pAdapterNode->pAdapter;
6284
6285 switch(pAdapter->device_mode)
6286 {
6287 case WLAN_HDD_INFRA_STATION:
6288 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006289 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306290
6291 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6292
Jeff Johnson295189b2012-06-20 16:38:30 -07006293 hdd_init_station_mode(pAdapter);
6294 /* Open the gates for HDD to receive Wext commands */
6295 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006296 pHddCtx->scan_info.mScanPending = FALSE;
6297 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006298
6299 //Trigger the initial scan
6300 hdd_wlan_initial_scan(pAdapter);
6301
6302 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306303 if (eConnectionState_Associated == connState ||
6304 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006305 {
6306 union iwreq_data wrqu;
6307 memset(&wrqu, '\0', sizeof(wrqu));
6308 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6309 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6310 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006311 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006312
Jeff Johnson295189b2012-06-20 16:38:30 -07006313 /* indicate disconnected event to nl80211 */
6314 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6315 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006316 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306317 else if (eConnectionState_Connecting == connState)
6318 {
6319 /*
6320 * Indicate connect failure to supplicant if we were in the
6321 * process of connecting
6322 */
6323 cfg80211_connect_result(pAdapter->dev, NULL,
6324 NULL, 0, NULL, 0,
6325 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6326 GFP_KERNEL);
6327 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006328 break;
6329
6330 case WLAN_HDD_SOFTAP:
6331 /* softAP can handle SSR */
6332 break;
6333
6334 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006335 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006336 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006337 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006338 break;
6339
6340 case WLAN_HDD_MONITOR:
6341 /* monitor interface start */
6342 break;
6343 default:
6344 break;
6345 }
6346
6347 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6348 pAdapterNode = pNext;
6349 }
6350
6351 EXIT();
6352
6353 return VOS_STATUS_SUCCESS;
6354}
6355
6356VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6357{
6358 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6359 hdd_adapter_t *pAdapter;
6360 VOS_STATUS status;
6361 v_U32_t roamId;
6362
6363 ENTER();
6364
6365 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6366
6367 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6368 {
6369 pAdapter = pAdapterNode->pAdapter;
6370
6371 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6372 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6373 {
6374 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6375 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6376
6377 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6378 init_completion(&pAdapter->disconnect_comp_var);
6379 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6380 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6381
6382 wait_for_completion_interruptible_timeout(
6383 &pAdapter->disconnect_comp_var,
6384 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6385
6386 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6387 pHddCtx->isAmpAllowed = VOS_FALSE;
6388 sme_RoamConnect(pHddCtx->hHal,
6389 pAdapter->sessionId, &(pWextState->roamProfile),
6390 &roamId);
6391 }
6392
6393 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6394 pAdapterNode = pNext;
6395 }
6396
6397 EXIT();
6398
6399 return VOS_STATUS_SUCCESS;
6400}
6401
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006402void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6403{
6404 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6405 VOS_STATUS status;
6406 hdd_adapter_t *pAdapter;
6407 hdd_station_ctx_t *pHddStaCtx;
6408 hdd_ap_ctx_t *pHddApCtx;
6409 hdd_hostapd_state_t * pHostapdState;
6410 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6411 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6412 const char *p2pMode = "DEV";
6413 const char *ccMode = "Standalone";
6414 int n;
6415
6416 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6417 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6418 {
6419 pAdapter = pAdapterNode->pAdapter;
6420 switch (pAdapter->device_mode) {
6421 case WLAN_HDD_INFRA_STATION:
6422 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6423 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6424 staChannel = pHddStaCtx->conn_info.operationChannel;
6425 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6426 }
6427 break;
6428 case WLAN_HDD_P2P_CLIENT:
6429 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6430 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6431 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6432 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6433 p2pMode = "CLI";
6434 }
6435 break;
6436 case WLAN_HDD_P2P_GO:
6437 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6438 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6439 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6440 p2pChannel = pHddApCtx->operatingChannel;
6441 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6442 }
6443 p2pMode = "GO";
6444 break;
6445 case WLAN_HDD_SOFTAP:
6446 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6447 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6448 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6449 apChannel = pHddApCtx->operatingChannel;
6450 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6451 }
6452 break;
6453 default:
6454 break;
6455 }
6456 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6457 pAdapterNode = pNext;
6458 }
6459 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6460 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6461 }
6462 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6463 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6464 if (p2pChannel > 0) {
6465 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6466 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6467 }
6468 if (apChannel > 0) {
6469 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6470 apChannel, MAC_ADDR_ARRAY(apBssid));
6471 }
6472
6473 if (p2pChannel > 0 && apChannel > 0) {
6474 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6475 }
6476}
6477
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006478bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006479{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006480 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006481}
6482
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006483/* Once SSR is disabled then it cannot be set. */
6484void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006485{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006486 if (HDD_SSR_DISABLED == isSsrRequired)
6487 return;
6488
Jeff Johnson295189b2012-06-20 16:38:30 -07006489 isSsrRequired = value;
6490}
6491
6492VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6493 hdd_adapter_list_node_t** ppAdapterNode)
6494{
6495 VOS_STATUS status;
6496 spin_lock(&pHddCtx->hddAdapters.lock);
6497 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6498 (hdd_list_node_t**) ppAdapterNode );
6499 spin_unlock(&pHddCtx->hddAdapters.lock);
6500 return status;
6501}
6502
6503VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6504 hdd_adapter_list_node_t* pAdapterNode,
6505 hdd_adapter_list_node_t** pNextAdapterNode)
6506{
6507 VOS_STATUS status;
6508 spin_lock(&pHddCtx->hddAdapters.lock);
6509 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6510 (hdd_list_node_t*) pAdapterNode,
6511 (hdd_list_node_t**)pNextAdapterNode );
6512
6513 spin_unlock(&pHddCtx->hddAdapters.lock);
6514 return status;
6515}
6516
6517VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6518 hdd_adapter_list_node_t* pAdapterNode)
6519{
6520 VOS_STATUS status;
6521 spin_lock(&pHddCtx->hddAdapters.lock);
6522 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6523 &pAdapterNode->node );
6524 spin_unlock(&pHddCtx->hddAdapters.lock);
6525 return status;
6526}
6527
6528VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6529 hdd_adapter_list_node_t** ppAdapterNode)
6530{
6531 VOS_STATUS status;
6532 spin_lock(&pHddCtx->hddAdapters.lock);
6533 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6534 (hdd_list_node_t**) ppAdapterNode );
6535 spin_unlock(&pHddCtx->hddAdapters.lock);
6536 return status;
6537}
6538
6539VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6540 hdd_adapter_list_node_t* pAdapterNode)
6541{
6542 VOS_STATUS status;
6543 spin_lock(&pHddCtx->hddAdapters.lock);
6544 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6545 (hdd_list_node_t*) pAdapterNode );
6546 spin_unlock(&pHddCtx->hddAdapters.lock);
6547 return status;
6548}
6549
6550VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6551 hdd_adapter_list_node_t* pAdapterNode)
6552{
6553 VOS_STATUS status;
6554 spin_lock(&pHddCtx->hddAdapters.lock);
6555 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6556 (hdd_list_node_t*) pAdapterNode );
6557 spin_unlock(&pHddCtx->hddAdapters.lock);
6558 return status;
6559}
6560
6561hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6562 tSirMacAddr macAddr )
6563{
6564 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6565 hdd_adapter_t *pAdapter;
6566 VOS_STATUS status;
6567
6568 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6569
6570 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6571 {
6572 pAdapter = pAdapterNode->pAdapter;
6573
6574 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6575 macAddr, sizeof(tSirMacAddr) ) )
6576 {
6577 return pAdapter;
6578 }
6579 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6580 pAdapterNode = pNext;
6581 }
6582
6583 return NULL;
6584
6585}
6586
6587hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6588{
6589 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6590 hdd_adapter_t *pAdapter;
6591 VOS_STATUS status;
6592
6593 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6594
6595 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6596 {
6597 pAdapter = pAdapterNode->pAdapter;
6598
6599 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6600 IFNAMSIZ ) )
6601 {
6602 return pAdapter;
6603 }
6604 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6605 pAdapterNode = pNext;
6606 }
6607
6608 return NULL;
6609
6610}
6611
6612hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6613{
6614 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6615 hdd_adapter_t *pAdapter;
6616 VOS_STATUS status;
6617
6618 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6619
6620 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6621 {
6622 pAdapter = pAdapterNode->pAdapter;
6623
6624 if( pAdapter && (mode == pAdapter->device_mode) )
6625 {
6626 return pAdapter;
6627 }
6628 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6629 pAdapterNode = pNext;
6630 }
6631
6632 return NULL;
6633
6634}
6635
6636//Remove this function later
6637hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6638{
6639 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6640 hdd_adapter_t *pAdapter;
6641 VOS_STATUS status;
6642
6643 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6644
6645 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6646 {
6647 pAdapter = pAdapterNode->pAdapter;
6648
6649 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6650 {
6651 return pAdapter;
6652 }
6653
6654 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6655 pAdapterNode = pNext;
6656 }
6657
6658 return NULL;
6659
6660}
6661
Jeff Johnson295189b2012-06-20 16:38:30 -07006662/**---------------------------------------------------------------------------
6663
6664 \brief hdd_set_monitor_tx_adapter() -
6665
6666 This API initializes the adapter to be used while transmitting on monitor
6667 adapter.
6668
6669 \param - pHddCtx - Pointer to the HDD context.
6670 pAdapter - Adapter that will used for TX. This can be NULL.
6671 \return - None.
6672 --------------------------------------------------------------------------*/
6673void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6674{
6675 hdd_adapter_t *pMonAdapter;
6676
6677 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6678
6679 if( NULL != pMonAdapter )
6680 {
6681 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6682 }
6683}
Jeff Johnson295189b2012-06-20 16:38:30 -07006684/**---------------------------------------------------------------------------
6685
6686 \brief hdd_select_queue() -
6687
6688 This API returns the operating channel of the requested device mode
6689
6690 \param - pHddCtx - Pointer to the HDD context.
6691 - mode - Device mode for which operating channel is required
6692 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6693 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6694 \return - channel number. "0" id the requested device is not found OR it is not connected.
6695 --------------------------------------------------------------------------*/
6696v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6697{
6698 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6699 VOS_STATUS status;
6700 hdd_adapter_t *pAdapter;
6701 v_U8_t operatingChannel = 0;
6702
6703 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6704
6705 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6706 {
6707 pAdapter = pAdapterNode->pAdapter;
6708
6709 if( mode == pAdapter->device_mode )
6710 {
6711 switch(pAdapter->device_mode)
6712 {
6713 case WLAN_HDD_INFRA_STATION:
6714 case WLAN_HDD_P2P_CLIENT:
6715 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6716 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6717 break;
6718 case WLAN_HDD_SOFTAP:
6719 case WLAN_HDD_P2P_GO:
6720 /*softap connection info */
6721 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6722 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6723 break;
6724 default:
6725 break;
6726 }
6727
6728 break; //Found the device of interest. break the loop
6729 }
6730
6731 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6732 pAdapterNode = pNext;
6733 }
6734 return operatingChannel;
6735}
6736
6737#ifdef WLAN_FEATURE_PACKET_FILTERING
6738/**---------------------------------------------------------------------------
6739
6740 \brief hdd_set_multicast_list() -
6741
6742 This used to set the multicast address list.
6743
6744 \param - dev - Pointer to the WLAN device.
6745 - skb - Pointer to OS packet (sk_buff).
6746 \return - success/fail
6747
6748 --------------------------------------------------------------------------*/
6749static void hdd_set_multicast_list(struct net_device *dev)
6750{
6751 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006752 int mc_count;
6753 int i = 0;
6754 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306755
6756 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006757 {
6758 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306759 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006760 return;
6761 }
6762
6763 if (dev->flags & IFF_ALLMULTI)
6764 {
6765 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006766 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306767 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006768 }
6769 else
6770 {
6771 mc_count = netdev_mc_count(dev);
6772 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006773 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006774 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6775 {
6776 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006777 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306778 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006779 return;
6780 }
6781
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306782 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006783
6784 netdev_for_each_mc_addr(ha, dev) {
6785 if (i == mc_count)
6786 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306787 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6788 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
6789 hddLog(VOS_TRACE_LEVEL_INFO, "\n%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006790 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306791 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006792 i++;
6793 }
6794 }
6795 return;
6796}
6797#endif
6798
6799/**---------------------------------------------------------------------------
6800
6801 \brief hdd_select_queue() -
6802
6803 This function is registered with the Linux OS for network
6804 core to decide which queue to use first.
6805
6806 \param - dev - Pointer to the WLAN device.
6807 - skb - Pointer to OS packet (sk_buff).
6808 \return - ac, Queue Index/access category corresponding to UP in IP header
6809
6810 --------------------------------------------------------------------------*/
6811v_U16_t hdd_select_queue(struct net_device *dev,
6812 struct sk_buff *skb)
6813{
6814 return hdd_wmm_select_queue(dev, skb);
6815}
6816
6817
6818/**---------------------------------------------------------------------------
6819
6820 \brief hdd_wlan_initial_scan() -
6821
6822 This function triggers the initial scan
6823
6824 \param - pAdapter - Pointer to the HDD adapter.
6825
6826 --------------------------------------------------------------------------*/
6827void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6828{
6829 tCsrScanRequest scanReq;
6830 tCsrChannelInfo channelInfo;
6831 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006832 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006833 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6834
6835 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6836 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6837 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6838
6839 if(sme_Is11dSupported(pHddCtx->hHal))
6840 {
6841 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6842 if ( HAL_STATUS_SUCCESS( halStatus ) )
6843 {
6844 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6845 if( !scanReq.ChannelInfo.ChannelList )
6846 {
6847 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6848 vos_mem_free(channelInfo.ChannelList);
6849 return;
6850 }
6851 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6852 channelInfo.numOfChannels);
6853 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6854 vos_mem_free(channelInfo.ChannelList);
6855 }
6856
6857 scanReq.scanType = eSIR_PASSIVE_SCAN;
6858 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6859 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6860 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6861 }
6862 else
6863 {
6864 scanReq.scanType = eSIR_ACTIVE_SCAN;
6865 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6866 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6867 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6868 }
6869
6870 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6871 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6872 {
6873 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6874 __func__, halStatus );
6875 }
6876
6877 if(sme_Is11dSupported(pHddCtx->hHal))
6878 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6879}
6880
6881struct fullPowerContext
6882{
6883 struct completion completion;
6884 unsigned int magic;
6885};
6886#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6887
6888/**---------------------------------------------------------------------------
6889
6890 \brief hdd_full_power_callback() - HDD full power callback function
6891
6892 This is the function invoked by SME to inform the result of a full power
6893 request issued by HDD
6894
6895 \param - callbackcontext - Pointer to cookie
6896 \param - status - result of request
6897
6898 \return - None
6899
6900 --------------------------------------------------------------------------*/
6901static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6902{
6903 struct fullPowerContext *pContext = callbackContext;
6904
6905 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306906 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006907
6908 if (NULL == callbackContext)
6909 {
6910 hddLog(VOS_TRACE_LEVEL_ERROR,
6911 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006912 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006913 return;
6914 }
6915
6916 /* there is a race condition that exists between this callback function
6917 and the caller since the caller could time out either before or
6918 while this code is executing. we'll assume the timeout hasn't
6919 occurred, but we'll verify that right before we save our work */
6920
6921 if (POWER_CONTEXT_MAGIC != pContext->magic)
6922 {
6923 /* the caller presumably timed out so there is nothing we can do */
6924 hddLog(VOS_TRACE_LEVEL_WARN,
6925 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006926 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006927 return;
6928 }
6929
6930 /* the race is on. caller could have timed out immediately after
6931 we verified the magic, but if so, caller will wait a short time
6932 for us to notify the caller, so the context will stay valid */
6933 complete(&pContext->completion);
6934}
6935
6936/**---------------------------------------------------------------------------
6937
6938 \brief hdd_wlan_exit() - HDD WLAN exit function
6939
6940 This is the driver exit point (invoked during rmmod)
6941
6942 \param - pHddCtx - Pointer to the HDD Context
6943
6944 \return - None
6945
6946 --------------------------------------------------------------------------*/
6947void hdd_wlan_exit(hdd_context_t *pHddCtx)
6948{
6949 eHalStatus halStatus;
6950 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6951 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306952 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006953 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006954 struct fullPowerContext powerContext;
6955 long lrc;
6956
6957 ENTER();
6958
Jeff Johnson88ba7742013-02-27 14:36:02 -08006959 if (VOS_FTM_MODE != hdd_get_conparam())
6960 {
6961 // Unloading, restart logic is no more required.
6962 wlan_hdd_restart_deinit(pHddCtx);
6963 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006964
Jeff Johnson295189b2012-06-20 16:38:30 -07006965 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006966 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006967 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006968 {
6969 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6970 WLAN_HDD_INFRA_STATION);
6971 if (pAdapter == NULL)
6972 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6973
6974 if (pAdapter != NULL)
6975 {
6976 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6977 hdd_UnregisterWext(pAdapter->dev);
6978 }
6979 }
6980 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006981
Jeff Johnson295189b2012-06-20 16:38:30 -07006982 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006983 {
6984 wlan_hdd_ftm_close(pHddCtx);
6985 goto free_hdd_ctx;
6986 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006987 //Stop the Interface TX queue.
6988 //netif_tx_disable(pWlanDev);
6989 //netif_carrier_off(pWlanDev);
6990
Jeff Johnson295189b2012-06-20 16:38:30 -07006991 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6992 {
6993 pAdapter = hdd_get_adapter(pHddCtx,
6994 WLAN_HDD_SOFTAP);
6995 }
6996 else
6997 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006998 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006999 {
7000 pAdapter = hdd_get_adapter(pHddCtx,
7001 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007002 if (pAdapter == NULL)
7003 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007004 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007005 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007006 /* DeRegister with platform driver as client for Suspend/Resume */
7007 vosStatus = hddDeregisterPmOps(pHddCtx);
7008 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7009 {
7010 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7011 VOS_ASSERT(0);
7012 }
7013
7014 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7015 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7016 {
7017 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7018 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007019
7020 // Cancel any outstanding scan requests. We are about to close all
7021 // of our adapters, but an adapter structure is what SME passes back
7022 // to our callback function. Hence if there are any outstanding scan
7023 // requests then there is a race condition between when the adapter
7024 // is closed and when the callback is invoked. We try to resolve that
7025 // race condition here by canceling any outstanding scans before we
7026 // close the adapters.
7027 // Note that the scans may be cancelled in an asynchronous manner, so
7028 // ideally there needs to be some kind of synchronization. Rather than
7029 // introduce a new synchronization here, we will utilize the fact that
7030 // we are about to Request Full Power, and since that is synchronized,
7031 // the expectation is that by the time Request Full Power has completed,
7032 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007033 if (NULL != pAdapter)
7034 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7035 else
7036 hddLog(VOS_TRACE_LEVEL_ERROR,
7037 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007038
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007039 //Stop the traffic monitor timer
7040 if ( VOS_TIMER_STATE_RUNNING ==
7041 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7042 {
7043 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7044 }
7045
7046 // Destroy the traffic monitor timer
7047 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7048 &pHddCtx->tx_rx_trafficTmr)))
7049 {
7050 hddLog(VOS_TRACE_LEVEL_ERROR,
7051 "%s: Cannot deallocate Traffic monitor timer", __func__);
7052 }
7053
Jeff Johnson295189b2012-06-20 16:38:30 -07007054 //Disable IMPS/BMPS as we do not want the device to enter any power
7055 //save mode during shutdown
7056 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7057 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7058 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7059
7060 //Ensure that device is in full power as we will touch H/W during vos_Stop
7061 init_completion(&powerContext.completion);
7062 powerContext.magic = POWER_CONTEXT_MAGIC;
7063
7064 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7065 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7066
7067 if (eHAL_STATUS_SUCCESS != halStatus)
7068 {
7069 if (eHAL_STATUS_PMC_PENDING == halStatus)
7070 {
7071 /* request was sent -- wait for the response */
7072 lrc = wait_for_completion_interruptible_timeout(
7073 &powerContext.completion,
7074 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
7075 /* either we have a response or we timed out
7076 either way, first invalidate our magic */
7077 powerContext.magic = 0;
7078 if (lrc <= 0)
7079 {
7080 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007081 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007082 /* there is a race condition such that the callback
7083 function could be executing at the same time we are. of
7084 primary concern is if the callback function had already
7085 verified the "magic" but hasn't yet set the completion
7086 variable. Since the completion variable is on our
7087 stack, we'll delay just a bit to make sure the data is
7088 still valid if that is the case */
7089 msleep(50);
7090 }
7091 }
7092 else
7093 {
7094 hddLog(VOS_TRACE_LEVEL_ERROR,
7095 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007096 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007097 VOS_ASSERT(0);
7098 /* continue -- need to clean up as much as possible */
7099 }
7100 }
7101
Yue Ma0d4891e2013-08-06 17:01:45 -07007102 hdd_debugfs_exit(pHddCtx);
7103
Jeff Johnson295189b2012-06-20 16:38:30 -07007104 // Unregister the Net Device Notifier
7105 unregister_netdevice_notifier(&hdd_netdev_notifier);
7106
Jeff Johnson295189b2012-06-20 16:38:30 -07007107 hdd_stop_all_adapters( pHddCtx );
7108
Jeff Johnson295189b2012-06-20 16:38:30 -07007109#ifdef WLAN_BTAMP_FEATURE
7110 vosStatus = WLANBAP_Stop(pVosContext);
7111 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7112 {
7113 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7114 "%s: Failed to stop BAP",__func__);
7115 }
7116#endif //WLAN_BTAMP_FEATURE
7117
7118 //Stop all the modules
7119 vosStatus = vos_stop( pVosContext );
7120 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7121 {
7122 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7123 "%s: Failed to stop VOSS",__func__);
7124 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7125 }
7126
Jeff Johnson295189b2012-06-20 16:38:30 -07007127 //Assert Deep sleep signal now to put Libra HW in lowest power state
7128 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7129 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7130
7131 //Vote off any PMIC voltage supplies
7132 vos_chipPowerDown(NULL, NULL, NULL);
7133
7134 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7135
Leo Chang59cdc7e2013-07-10 10:08:21 -07007136
Jeff Johnson295189b2012-06-20 16:38:30 -07007137 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007138 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007139
7140 //Close the scheduler before calling vos_close to make sure no thread is
7141 // scheduled after the each module close is called i.e after all the data
7142 // structures are freed.
7143 vosStatus = vos_sched_close( pVosContext );
7144 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7145 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7146 "%s: Failed to close VOSS Scheduler",__func__);
7147 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7148 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007149#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007150#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7151 /* Destroy the wake lock */
7152 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7153#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007154 /* Destroy the wake lock */
7155 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007156#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007157
7158 //Close VOSS
7159 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7160 vos_close(pVosContext);
7161
Jeff Johnson295189b2012-06-20 16:38:30 -07007162 //Close Watchdog
7163 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7164 vos_watchdog_close(pVosContext);
7165
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307166 //Clean up HDD Nlink Service
7167 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007168#ifdef WLAN_KD_READY_NOTIFIER
7169 nl_srv_exit(pHddCtx->ptt_pid);
7170#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307171 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007172#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307173
Jeff Johnson295189b2012-06-20 16:38:30 -07007174 /* Cancel the vote for XO Core ON.
7175 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7176 * exited at this point
7177 */
7178 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
7179 " when WLAN is turned OFF\n");
7180 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7181 {
7182 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7183 " Not returning failure."
7184 " Power consumed will be high\n");
7185 }
7186
7187 hdd_close_all_adapters( pHddCtx );
7188
7189
7190 //Free up dynamically allocated members inside HDD Adapter
7191 kfree(pHddCtx->cfg_ini);
7192 pHddCtx->cfg_ini= NULL;
7193
7194 /* free the power on lock from platform driver */
7195 if (free_riva_power_on_lock("wlan"))
7196 {
7197 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7198 __func__);
7199 }
7200
Jeff Johnson88ba7742013-02-27 14:36:02 -08007201free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007202 /* FTM mode, WIPHY did not registered
7203 If un-register here, system crash will happen */
7204 if (VOS_FTM_MODE != hdd_get_conparam())
7205 {
7206 wiphy_unregister(wiphy) ;
7207 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007208 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007209 if (hdd_is_ssr_required())
7210 {
7211 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007212 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007213 msleep(5000);
7214 }
7215 hdd_set_ssr_required (VOS_FALSE);
7216}
7217
7218
7219/**---------------------------------------------------------------------------
7220
7221 \brief hdd_update_config_from_nv() - Function to update the contents of
7222 the running configuration with parameters taken from NV storage
7223
7224 \param - pHddCtx - Pointer to the HDD global context
7225
7226 \return - VOS_STATUS_SUCCESS if successful
7227
7228 --------------------------------------------------------------------------*/
7229static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7230{
Jeff Johnson295189b2012-06-20 16:38:30 -07007231 v_BOOL_t itemIsValid = VOS_FALSE;
7232 VOS_STATUS status;
7233 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7234 v_U8_t macLoop;
7235
7236 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7237 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7238 if(status != VOS_STATUS_SUCCESS)
7239 {
7240 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed\n ");
7241 return VOS_STATUS_E_FAILURE;
7242 }
7243
7244 if (itemIsValid == VOS_TRUE)
7245 {
7246 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV\n ");
7247 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7248 VOS_MAX_CONCURRENCY_PERSONA);
7249 if(status != VOS_STATUS_SUCCESS)
7250 {
7251 /* Get MAC from NV fail, not update CFG info
7252 * INI MAC value will be used for MAC setting */
7253 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed\n ");
7254 return VOS_STATUS_E_FAILURE;
7255 }
7256
7257 /* If first MAC is not valid, treat all others are not valid
7258 * Then all MACs will be got from ini file */
7259 if(vos_is_macaddr_zero(&macFromNV[0]))
7260 {
7261 /* MAC address in NV file is not configured yet */
7262 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7263 return VOS_STATUS_E_INVAL;
7264 }
7265
7266 /* Get MAC address from NV, update CFG info */
7267 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7268 {
7269 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7270 {
7271 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7272 /* This MAC is not valid, skip it
7273 * This MAC will be got from ini file */
7274 }
7275 else
7276 {
7277 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7278 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7279 VOS_MAC_ADDR_SIZE);
7280 }
7281 }
7282 }
7283 else
7284 {
7285 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7286 return VOS_STATUS_E_FAILURE;
7287 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007288
Jeff Johnson295189b2012-06-20 16:38:30 -07007289
7290 return VOS_STATUS_SUCCESS;
7291}
7292
7293/**---------------------------------------------------------------------------
7294
7295 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7296
7297 \param - pAdapter - Pointer to the HDD
7298
7299 \return - None
7300
7301 --------------------------------------------------------------------------*/
7302VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7303{
7304 eHalStatus halStatus;
7305 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307306 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007307
Jeff Johnson295189b2012-06-20 16:38:30 -07007308
7309 // Send ready indication to the HDD. This will kick off the MAC
7310 // into a 'running' state and should kick off an initial scan.
7311 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7312 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7313 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307314 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007315 "code %08d [x%08x]",__func__, halStatus, halStatus );
7316 return VOS_STATUS_E_FAILURE;
7317 }
7318
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307319 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007320 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7321 // And RIVA will crash
7322 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7323 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307324 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7325 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7326
7327
Jeff Johnson295189b2012-06-20 16:38:30 -07007328 return VOS_STATUS_SUCCESS;
7329}
7330
Jeff Johnson295189b2012-06-20 16:38:30 -07007331/* wake lock APIs for HDD */
7332void hdd_prevent_suspend(void)
7333{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007334#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007335 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007336#else
7337 wcnss_prevent_suspend();
7338#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007339}
7340
7341void hdd_allow_suspend(void)
7342{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007343#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007344 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007345#else
7346 wcnss_allow_suspend();
7347#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007348}
7349
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007350void hdd_allow_suspend_timeout(v_U32_t timeout)
7351{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007352#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007353 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007354#else
7355 /* Do nothing as there is no API in wcnss for timeout*/
7356#endif
7357}
7358
Jeff Johnson295189b2012-06-20 16:38:30 -07007359/**---------------------------------------------------------------------------
7360
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007361 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7362 information between Host and Riva
7363
7364 This function gets reported version of FW
7365 It also finds the version of Riva headers used to compile the host
7366 It compares the above two and prints a warning if they are different
7367 It gets the SW and HW version string
7368 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7369 indicating the features they support through a bitmap
7370
7371 \param - pHddCtx - Pointer to HDD context
7372
7373 \return - void
7374
7375 --------------------------------------------------------------------------*/
7376
7377void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7378{
7379
7380 tSirVersionType versionCompiled;
7381 tSirVersionType versionReported;
7382 tSirVersionString versionString;
7383 tANI_U8 fwFeatCapsMsgSupported = 0;
7384 VOS_STATUS vstatus;
7385
7386 /* retrieve and display WCNSS version information */
7387 do {
7388
7389 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7390 &versionCompiled);
7391 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7392 {
7393 hddLog(VOS_TRACE_LEVEL_FATAL,
7394 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007395 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007396 break;
7397 }
7398
7399 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7400 &versionReported);
7401 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7402 {
7403 hddLog(VOS_TRACE_LEVEL_FATAL,
7404 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007405 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007406 break;
7407 }
7408
7409 if ((versionCompiled.major != versionReported.major) ||
7410 (versionCompiled.minor != versionReported.minor) ||
7411 (versionCompiled.version != versionReported.version) ||
7412 (versionCompiled.revision != versionReported.revision))
7413 {
7414 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7415 "Host expected %u.%u.%u.%u\n",
7416 WLAN_MODULE_NAME,
7417 (int)versionReported.major,
7418 (int)versionReported.minor,
7419 (int)versionReported.version,
7420 (int)versionReported.revision,
7421 (int)versionCompiled.major,
7422 (int)versionCompiled.minor,
7423 (int)versionCompiled.version,
7424 (int)versionCompiled.revision);
7425 }
7426 else
7427 {
7428 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7429 WLAN_MODULE_NAME,
7430 (int)versionReported.major,
7431 (int)versionReported.minor,
7432 (int)versionReported.version,
7433 (int)versionReported.revision);
7434 }
7435
7436 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7437 versionString,
7438 sizeof(versionString));
7439 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7440 {
7441 hddLog(VOS_TRACE_LEVEL_FATAL,
7442 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007443 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007444 break;
7445 }
7446
7447 pr_info("%s: WCNSS software version %s\n",
7448 WLAN_MODULE_NAME, versionString);
7449
7450 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7451 versionString,
7452 sizeof(versionString));
7453 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7454 {
7455 hddLog(VOS_TRACE_LEVEL_FATAL,
7456 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007457 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007458 break;
7459 }
7460
7461 pr_info("%s: WCNSS hardware version %s\n",
7462 WLAN_MODULE_NAME, versionString);
7463
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007464 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7465 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007466 send the message only if it the riva is 1.1
7467 minor numbers for different riva branches:
7468 0 -> (1.0)Mainline Build
7469 1 -> (1.1)Mainline Build
7470 2->(1.04) Stability Build
7471 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007472 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007473 ((versionReported.minor>=1) && (versionReported.version>=1)))
7474 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7475 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007476
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007477 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007478 {
7479#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7480 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7481 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7482#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007483 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7484 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7485 {
7486 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7487 }
7488
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007489 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007490 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007491
7492 } while (0);
7493
7494}
7495
7496/**---------------------------------------------------------------------------
7497
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307498 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7499
7500 \param - pHddCtx - Pointer to the hdd context
7501
7502 \return - true if hardware supports 5GHz
7503
7504 --------------------------------------------------------------------------*/
7505static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7506{
7507 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7508 * then hardware support 5Ghz.
7509 */
7510 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7511 {
7512 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7513 return true;
7514 }
7515 else
7516 {
7517 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7518 __func__);
7519 return false;
7520 }
7521}
7522
7523
7524/**---------------------------------------------------------------------------
7525
Jeff Johnson295189b2012-06-20 16:38:30 -07007526 \brief hdd_wlan_startup() - HDD init function
7527
7528 This is the driver startup code executed once a WLAN device has been detected
7529
7530 \param - dev - Pointer to the underlying device
7531
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007532 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007533
7534 --------------------------------------------------------------------------*/
7535
7536int hdd_wlan_startup(struct device *dev )
7537{
7538 VOS_STATUS status;
7539 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007540 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007541 hdd_context_t *pHddCtx = NULL;
7542 v_CONTEXT_t pVosContext= NULL;
7543#ifdef WLAN_BTAMP_FEATURE
7544 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7545 WLANBAP_ConfigType btAmpConfig;
7546 hdd_config_t *pConfig;
7547#endif
7548 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007549 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007550
7551 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007552 /*
7553 * cfg80211: wiphy allocation
7554 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307555 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007556
7557 if(wiphy == NULL)
7558 {
7559 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007560 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007561 }
7562
7563 pHddCtx = wiphy_priv(wiphy);
7564
Jeff Johnson295189b2012-06-20 16:38:30 -07007565 //Initialize the adapter context to zeros.
7566 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7567
Jeff Johnson295189b2012-06-20 16:38:30 -07007568 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007569 hdd_prevent_suspend();
7570 pHddCtx->isLoadUnloadInProgress = TRUE;
7571
7572 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7573
7574 /*Get vos context here bcoz vos_open requires it*/
7575 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7576
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007577 if(pVosContext == NULL)
7578 {
7579 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7580 goto err_free_hdd_context;
7581 }
7582
Jeff Johnson295189b2012-06-20 16:38:30 -07007583 //Save the Global VOSS context in adapter context for future.
7584 pHddCtx->pvosContext = pVosContext;
7585
7586 //Save the adapter context in global context for future.
7587 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7588
Jeff Johnson295189b2012-06-20 16:38:30 -07007589 pHddCtx->parent_dev = dev;
7590
7591 init_completion(&pHddCtx->full_pwr_comp_var);
7592 init_completion(&pHddCtx->standby_comp_var);
7593 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007594 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007595 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307596 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007597
7598#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007599 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007600#else
7601 init_completion(&pHddCtx->driver_crda_req);
7602#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007603
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307604 spin_lock_init(&pHddCtx->schedScan_lock);
7605
Jeff Johnson295189b2012-06-20 16:38:30 -07007606 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7607
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307608#ifdef FEATURE_WLAN_TDLS
7609 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7610 * invoked by other instances also) to protect the concurrent
7611 * access for the Adapters by TDLS module.
7612 */
7613 mutex_init(&pHddCtx->tdls_lock);
7614#endif
7615
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307616 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007617 // Load all config first as TL config is needed during vos_open
7618 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7619 if(pHddCtx->cfg_ini == NULL)
7620 {
7621 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7622 goto err_free_hdd_context;
7623 }
7624
7625 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7626
7627 // Read and parse the qcom_cfg.ini file
7628 status = hdd_parse_config_ini( pHddCtx );
7629 if ( VOS_STATUS_SUCCESS != status )
7630 {
7631 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7632 __func__, WLAN_INI_FILE);
7633 goto err_config;
7634 }
7635
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307636 /* INI has been read, initialise the configuredMcastBcastFilter with
7637 * INI value as this will serve as the default value
7638 */
7639 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7640 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7641 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307642
7643 if (false == hdd_is_5g_supported(pHddCtx))
7644 {
7645 //5Ghz is not supported.
7646 if (1 != pHddCtx->cfg_ini->nBandCapability)
7647 {
7648 hddLog(VOS_TRACE_LEVEL_INFO,
7649 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7650 pHddCtx->cfg_ini->nBandCapability = 1;
7651 }
7652 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307653
7654 /* If SNR Monitoring is enabled, FW has to parse all beacons
7655 * for calcaluting and storing the average SNR, so set Nth beacon
7656 * filter to 1 to enable FW to parse all the beaocons
7657 */
7658 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7659 {
7660 /* The log level is deliberately set to WARN as overriding
7661 * nthBeaconFilter to 1 will increase power cosumption and this
7662 * might just prove helpful to detect the power issue.
7663 */
7664 hddLog(VOS_TRACE_LEVEL_WARN,
7665 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7666 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7667 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007668 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307669 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007670 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307671 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007672 {
7673 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307674 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7675 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007676 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007677
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007678 // Update VOS trace levels based upon the cfg.ini
7679 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7680 pHddCtx->cfg_ini->vosTraceEnableBAP);
7681 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7682 pHddCtx->cfg_ini->vosTraceEnableTL);
7683 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7684 pHddCtx->cfg_ini->vosTraceEnableWDI);
7685 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7686 pHddCtx->cfg_ini->vosTraceEnableHDD);
7687 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7688 pHddCtx->cfg_ini->vosTraceEnableSME);
7689 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7690 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307691 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7692 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007693 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7694 pHddCtx->cfg_ini->vosTraceEnableWDA);
7695 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7696 pHddCtx->cfg_ini->vosTraceEnableSYS);
7697 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7698 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007699 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7700 pHddCtx->cfg_ini->vosTraceEnableSAP);
7701 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7702 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007703
Jeff Johnson295189b2012-06-20 16:38:30 -07007704 // Update WDI trace levels based upon the cfg.ini
7705 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7706 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7707 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7708 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7709 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7710 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7711 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7712 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007713
Jeff Johnson88ba7742013-02-27 14:36:02 -08007714 if (VOS_FTM_MODE == hdd_get_conparam())
7715 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007716 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7717 {
7718 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7719 goto err_free_hdd_context;
7720 }
7721 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7722 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007723 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007724
Jeff Johnson88ba7742013-02-27 14:36:02 -08007725 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007726 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7727 {
7728 status = vos_watchdog_open(pVosContext,
7729 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7730
7731 if(!VOS_IS_STATUS_SUCCESS( status ))
7732 {
7733 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307734 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007735 }
7736 }
7737
7738 pHddCtx->isLogpInProgress = FALSE;
7739 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7740
Jeff Johnson295189b2012-06-20 16:38:30 -07007741 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7742 if(!VOS_IS_STATUS_SUCCESS(status))
7743 {
7744 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007745 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007746 }
7747
Amar Singhala49cbc52013-10-08 18:37:44 -07007748#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007749 /* initialize the NV module. This is required so that
7750 we can initialize the channel information in wiphy
7751 from the NV.bin data. The channel information in
7752 wiphy needs to be initialized before wiphy registration */
7753
7754 status = vos_nv_open();
7755 if (!VOS_IS_STATUS_SUCCESS(status))
7756 {
7757 /* NV module cannot be initialized */
7758 hddLog( VOS_TRACE_LEVEL_FATAL,
7759 "%s: vos_nv_open failed", __func__);
7760 goto err_clkvote;
7761 }
7762
7763 status = vos_init_wiphy_from_nv_bin();
7764 if (!VOS_IS_STATUS_SUCCESS(status))
7765 {
7766 /* NV module cannot be initialized */
7767 hddLog( VOS_TRACE_LEVEL_FATAL,
7768 "%s: vos_init_wiphy failed", __func__);
7769 goto err_vos_nv_close;
7770 }
7771
Amar Singhala49cbc52013-10-08 18:37:44 -07007772 /* registration of wiphy dev with cfg80211 */
7773 if (0 > wlan_hdd_cfg80211_register(wiphy))
7774 {
7775 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007776 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007777 }
7778#endif
7779
Jeff Johnson295189b2012-06-20 16:38:30 -07007780 status = vos_open( &pVosContext, 0);
7781 if ( !VOS_IS_STATUS_SUCCESS( status ))
7782 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007783 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007784 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007785 }
7786
Jeff Johnson295189b2012-06-20 16:38:30 -07007787 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7788
7789 if ( NULL == pHddCtx->hHal )
7790 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007791 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007792 goto err_vosclose;
7793 }
7794
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007795 status = vos_preStart( pHddCtx->pvosContext );
7796 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7797 {
7798 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7799 goto err_vosclose;
7800 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007801
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007802 /* Note that the vos_preStart() sequence triggers the cfg download.
7803 The cfg download must occur before we update the SME config
7804 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007805 status = hdd_set_sme_config( pHddCtx );
7806
7807 if ( VOS_STATUS_SUCCESS != status )
7808 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007809 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7810 goto err_vosclose;
7811 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007812
7813 //Initialize the WMM module
7814 status = hdd_wmm_init(pHddCtx);
7815 if (!VOS_IS_STATUS_SUCCESS(status))
7816 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007817 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007818 goto err_vosclose;
7819 }
7820
Jeff Johnson295189b2012-06-20 16:38:30 -07007821 /* In the integrated architecture we update the configuration from
7822 the INI file and from NV before vOSS has been started so that
7823 the final contents are available to send down to the cCPU */
7824
Arif Hussain66559122013-11-21 10:11:40 -08007825 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
7826 {
7827 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
7828 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
7829 __func__, enable_dfs_chan_scan);
7830 }
7831 if (0 == enable_11d || 1 == enable_11d)
7832 {
7833 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
7834 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
7835 __func__, enable_11d);
7836 }
7837
Jeff Johnson295189b2012-06-20 16:38:30 -07007838 // Apply the cfg.ini to cfg.dat
7839 if (FALSE == hdd_update_config_dat(pHddCtx))
7840 {
7841 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7842 goto err_vosclose;
7843 }
7844
7845 // Apply the NV to cfg.dat
7846 /* Prima Update MAC address only at here */
7847 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7848 {
7849#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7850 /* There was not a valid set of MAC Addresses in NV. See if the
7851 default addresses were modified by the cfg.ini settings. If so,
7852 we'll use them, but if not, we'll autogenerate a set of MAC
7853 addresses based upon the device serial number */
7854
7855 static const v_MACADDR_t default_address =
7856 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7857 unsigned int serialno;
7858 int i;
7859
7860 serialno = wcnss_get_serial_number();
7861 if ((0 != serialno) &&
7862 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7863 sizeof(default_address))))
7864 {
7865 /* cfg.ini has the default address, invoke autogen logic */
7866
7867 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7868 bytes of the serial number that can be used to generate
7869 the other 3 bytes of the MAC address. Mask off all but
7870 the lower 3 bytes (this will also make sure we don't
7871 overflow in the next step) */
7872 serialno &= 0x00FFFFFF;
7873
7874 /* we need a unique address for each session */
7875 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7876
7877 /* autogen all addresses */
7878 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7879 {
7880 /* start with the entire default address */
7881 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7882 /* then replace the lower 3 bytes */
7883 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7884 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7885 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7886
7887 serialno++;
7888 }
7889
7890 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7891 MAC_ADDRESS_STR,
7892 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7893 }
7894 else
7895#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7896 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007897 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007898 "%s: Invalid MAC address in NV, using MAC from ini file "
7899 MAC_ADDRESS_STR, __func__,
7900 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7901 }
7902 }
7903 {
7904 eHalStatus halStatus;
7905 // Set the MAC Address
7906 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7907 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7908 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7909 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7910
7911 if (!HAL_STATUS_SUCCESS( halStatus ))
7912 {
7913 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7914 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007915 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007916 }
7917 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007918
7919 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7920 Note: Firmware image will be read and downloaded inside vos_start API */
7921 status = vos_start( pHddCtx->pvosContext );
7922 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7923 {
7924 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7925 goto err_vosclose;
7926 }
7927
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007928 /* Exchange capability info between Host and FW and also get versioning info from FW */
7929 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007930
7931 status = hdd_post_voss_start_config( pHddCtx );
7932 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7933 {
7934 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7935 __func__);
7936 goto err_vosstop;
7937 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007938
7939#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307940 wlan_hdd_cfg80211_update_reg_info( wiphy );
7941
7942 /* registration of wiphy dev with cfg80211 */
7943 if (0 > wlan_hdd_cfg80211_register(wiphy))
7944 {
7945 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7946 goto err_vosstop;
7947 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007948#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007949
Jeff Johnson295189b2012-06-20 16:38:30 -07007950 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7951 {
7952 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7953 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7954 }
7955 else
7956 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007957 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7958 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7959 if (pAdapter != NULL)
7960 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307961 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007962 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307963 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7964 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7965 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007966
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307967 /* Generate the P2P Device Address. This consists of the device's
7968 * primary MAC address with the locally administered bit set.
7969 */
7970 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007971 }
7972 else
7973 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307974 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7975 if (p2p_dev_addr != NULL)
7976 {
7977 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7978 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7979 }
7980 else
7981 {
7982 hddLog(VOS_TRACE_LEVEL_FATAL,
7983 "%s: Failed to allocate mac_address for p2p_device",
7984 __func__);
7985 goto err_close_adapter;
7986 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007987 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007988
7989 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7990 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7991 if ( NULL == pP2pAdapter )
7992 {
7993 hddLog(VOS_TRACE_LEVEL_FATAL,
7994 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007995 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007996 goto err_close_adapter;
7997 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007998 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007999 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008000
8001 if( pAdapter == NULL )
8002 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008003 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8004 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008005 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008006
Arif Hussain66559122013-11-21 10:11:40 -08008007 if (country_code)
8008 {
8009 eHalStatus ret;
8010 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8011#ifndef CONFIG_ENABLE_LINUX_REG
8012 hdd_checkandupdate_phymode(pAdapter, country_code);
8013#endif
8014 ret = sme_ChangeCountryCode(pHddCtx->hHal, NULL,
8015 country_code,
8016 pAdapter, pHddCtx->pvosContext,
8017 eSIR_TRUE);
8018 if (eHAL_STATUS_SUCCESS == ret)
8019 {
8020 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8021 "%s: SME Change Country code from module param fail ret=%d",
8022 __func__, ret);
8023 }
8024 else
8025 {
8026 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module country code set to %c%c",
8027 __func__, country_code[0], country_code[1]);
8028 }
8029 }
8030
Jeff Johnson295189b2012-06-20 16:38:30 -07008031#ifdef WLAN_BTAMP_FEATURE
8032 vStatus = WLANBAP_Open(pVosContext);
8033 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8034 {
8035 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8036 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008037 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008038 }
8039
8040 vStatus = BSL_Init(pVosContext);
8041 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8042 {
8043 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8044 "%s: Failed to Init BSL",__func__);
8045 goto err_bap_close;
8046 }
8047 vStatus = WLANBAP_Start(pVosContext);
8048 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8049 {
8050 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8051 "%s: Failed to start TL",__func__);
8052 goto err_bap_close;
8053 }
8054
8055 pConfig = pHddCtx->cfg_ini;
8056 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8057 status = WLANBAP_SetConfig(&btAmpConfig);
8058
8059#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008060
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008061#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8062 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8063 {
8064 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8065 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8066 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8067 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8068 }
8069#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008070#ifdef FEATURE_WLAN_SCAN_PNO
8071 /*SME must send channel update configuration to RIVA*/
8072 sme_UpdateChannelConfig(pHddCtx->hHal);
8073#endif
8074
Jeff Johnson295189b2012-06-20 16:38:30 -07008075 /* Register with platform driver as client for Suspend/Resume */
8076 status = hddRegisterPmOps(pHddCtx);
8077 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8078 {
8079 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8080#ifdef WLAN_BTAMP_FEATURE
8081 goto err_bap_stop;
8082#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008083 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008084#endif //WLAN_BTAMP_FEATURE
8085 }
8086
Yue Ma0d4891e2013-08-06 17:01:45 -07008087 /* Open debugfs interface */
8088 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8089 {
8090 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8091 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008092 }
8093
Jeff Johnson295189b2012-06-20 16:38:30 -07008094 /* Register TM level change handler function to the platform */
8095 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8096 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8097 {
8098 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8099 goto err_unregister_pmops;
8100 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008101
8102 /* register for riva power on lock to platform driver */
8103 if (req_riva_power_on_lock("wlan"))
8104 {
8105 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8106 __func__);
8107 goto err_unregister_pmops;
8108 }
8109
Jeff Johnson295189b2012-06-20 16:38:30 -07008110 // register net device notifier for device change notification
8111 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8112
8113 if(ret < 0)
8114 {
8115 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8116 goto err_free_power_on_lock;
8117 }
8118
8119 //Initialize the nlink service
8120 if(nl_srv_init() != 0)
8121 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308122 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008123 goto err_reg_netdev;
8124 }
8125
Leo Chang4ce1cc52013-10-21 18:27:15 -07008126#ifdef WLAN_KD_READY_NOTIFIER
8127 pHddCtx->kd_nl_init = 1;
8128#endif /* WLAN_KD_READY_NOTIFIER */
8129
Jeff Johnson295189b2012-06-20 16:38:30 -07008130 //Initialize the BTC service
8131 if(btc_activate_service(pHddCtx) != 0)
8132 {
8133 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8134 goto err_nl_srv;
8135 }
8136
8137#ifdef PTT_SOCK_SVC_ENABLE
8138 //Initialize the PTT service
8139 if(ptt_sock_activate_svc(pHddCtx) != 0)
8140 {
8141 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8142 goto err_nl_srv;
8143 }
8144#endif
8145
Jeff Johnson295189b2012-06-20 16:38:30 -07008146 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008147 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008148 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008149 /* Action frame registered in one adapter which will
8150 * applicable to all interfaces
8151 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008152 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008153 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008154
8155 mutex_init(&pHddCtx->sap_lock);
8156
8157 pHddCtx->isLoadUnloadInProgress = FALSE;
8158
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008159#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008160#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8161 /* Initialize the wake lcok */
8162 wake_lock_init(&pHddCtx->rx_wake_lock,
8163 WAKE_LOCK_SUSPEND,
8164 "qcom_rx_wakelock");
8165#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008166 /* Initialize the wake lcok */
8167 wake_lock_init(&pHddCtx->sap_wake_lock,
8168 WAKE_LOCK_SUSPEND,
8169 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008170#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008171
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008172 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8173 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008174
8175 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8176 hdd_allow_suspend();
Gopichand Nakkala8c0386c2013-07-09 23:31:37 +05308177
Jeff Johnsone7245742012-09-05 17:12:55 -07008178 // Initialize the restart logic
8179 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308180
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008181 //Register the traffic monitor timer now
8182 if ( pHddCtx->cfg_ini->dynSplitscan)
8183 {
8184 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8185 VOS_TIMER_TYPE_SW,
8186 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8187 (void *)pHddCtx);
8188 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008189 goto success;
8190
8191err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008192#ifdef WLAN_KD_READY_NOTIFIER
8193 nl_srv_exit(pHddCtx->ptt_pid);
8194#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008195 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008196#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008197err_reg_netdev:
8198 unregister_netdevice_notifier(&hdd_netdev_notifier);
8199
8200err_free_power_on_lock:
8201 free_riva_power_on_lock("wlan");
8202
8203err_unregister_pmops:
8204 hddDevTmUnregisterNotifyCallback(pHddCtx);
8205 hddDeregisterPmOps(pHddCtx);
8206
Yue Ma0d4891e2013-08-06 17:01:45 -07008207 hdd_debugfs_exit(pHddCtx);
8208
Jeff Johnson295189b2012-06-20 16:38:30 -07008209#ifdef WLAN_BTAMP_FEATURE
8210err_bap_stop:
8211 WLANBAP_Stop(pVosContext);
8212#endif
8213
8214#ifdef WLAN_BTAMP_FEATURE
8215err_bap_close:
8216 WLANBAP_Close(pVosContext);
8217#endif
8218
Jeff Johnson295189b2012-06-20 16:38:30 -07008219err_close_adapter:
8220 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008221
8222#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308223 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008224#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008225
8226err_vosstop:
8227 vos_stop(pVosContext);
8228
Amar Singhala49cbc52013-10-08 18:37:44 -07008229err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008230 status = vos_sched_close( pVosContext );
8231 if (!VOS_IS_STATUS_SUCCESS(status)) {
8232 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8233 "%s: Failed to close VOSS Scheduler", __func__);
8234 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8235 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008236 vos_close(pVosContext );
8237
8238err_wiphy_unregister:
8239
8240#ifdef CONFIG_ENABLE_LINUX_REG
8241 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008242
Amar Singhal0a402232013-10-11 20:57:16 -07008243err_vos_nv_close:
8244
8245 vos_nv_close();
8246
Jeff Johnson295189b2012-06-20 16:38:30 -07008247err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008248#endif
8249
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008250 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008251
8252err_wdclose:
8253 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8254 vos_watchdog_close(pVosContext);
8255
Jeff Johnson295189b2012-06-20 16:38:30 -07008256err_config:
8257 kfree(pHddCtx->cfg_ini);
8258 pHddCtx->cfg_ini= NULL;
8259
8260err_free_hdd_context:
8261 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008262 wiphy_free(wiphy) ;
8263 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008264 VOS_BUG(1);
8265
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008266 if (hdd_is_ssr_required())
8267 {
8268 /* WDI timeout had happened during load, so SSR is needed here */
8269 subsystem_restart("wcnss");
8270 msleep(5000);
8271 }
8272 hdd_set_ssr_required (VOS_FALSE);
8273
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008274 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008275
8276success:
8277 EXIT();
8278 return 0;
8279}
8280
8281/**---------------------------------------------------------------------------
8282
Jeff Johnson32d95a32012-09-10 13:15:23 -07008283 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008284
Jeff Johnson32d95a32012-09-10 13:15:23 -07008285 This is the driver entry point - called in different timeline depending
8286 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008287
8288 \param - None
8289
8290 \return - 0 for success, non zero for failure
8291
8292 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008293static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008294{
8295 VOS_STATUS status;
8296 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008297 struct device *dev = NULL;
8298 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008299#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8300 int max_retries = 0;
8301#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008302
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308303#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8304 vos_wconn_trace_init();
8305#endif
8306
Jeff Johnson295189b2012-06-20 16:38:30 -07008307 ENTER();
8308
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008309#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008310 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008311#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008312
8313 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8314 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8315
8316 //Power Up Libra WLAN card first if not already powered up
8317 status = vos_chipPowerUp(NULL,NULL,NULL);
8318 if (!VOS_IS_STATUS_SUCCESS(status))
8319 {
8320 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8321 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308322#ifdef WLAN_OPEN_SOURCE
8323 wake_lock_destroy(&wlan_wake_lock);
8324#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008325 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008326 }
8327
Jeff Johnson295189b2012-06-20 16:38:30 -07008328#ifdef ANI_BUS_TYPE_PCI
8329
8330 dev = wcnss_wlan_get_device();
8331
8332#endif // ANI_BUS_TYPE_PCI
8333
8334#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008335
8336#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8337 /* wait until WCNSS driver downloads NV */
8338 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8339 msleep(1000);
8340 }
8341 if (max_retries >= 5) {
8342 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308343#ifdef WLAN_OPEN_SOURCE
8344 wake_lock_destroy(&wlan_wake_lock);
8345#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008346 return -ENODEV;
8347 }
8348#endif
8349
Jeff Johnson295189b2012-06-20 16:38:30 -07008350 dev = wcnss_wlan_get_device();
8351#endif // ANI_BUS_TYPE_PLATFORM
8352
8353
8354 do {
8355 if (NULL == dev) {
8356 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8357 ret_status = -1;
8358 break;
8359 }
8360
8361#ifdef MEMORY_DEBUG
8362 vos_mem_init();
8363#endif
8364
8365#ifdef TIMER_MANAGER
8366 vos_timer_manager_init();
8367#endif
8368
8369 /* Preopen VOSS so that it is ready to start at least SAL */
8370 status = vos_preOpen(&pVosContext);
8371
8372 if (!VOS_IS_STATUS_SUCCESS(status))
8373 {
8374 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8375 ret_status = -1;
8376 break;
8377 }
8378
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008379#ifndef MODULE
8380 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8381 */
8382 hdd_set_conparam((v_UINT_t)con_mode);
8383#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008384
8385 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008386 if (hdd_wlan_startup(dev))
8387 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008388 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008389 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008390 vos_preClose( &pVosContext );
8391 ret_status = -1;
8392 break;
8393 }
8394
8395 /* Cancel the vote for XO Core ON
8396 * This is done here for safety purposes in case we re-initialize without turning
8397 * it OFF in any error scenario.
8398 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008399 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008400 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008401 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008402 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8403 {
8404 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
8405 " Power consumed will be high\n");
8406 }
8407 } while (0);
8408
8409 if (0 != ret_status)
8410 {
8411 //Assert Deep sleep signal now to put Libra HW in lowest power state
8412 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8413 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8414
8415 //Vote off any PMIC voltage supplies
8416 vos_chipPowerDown(NULL, NULL, NULL);
8417#ifdef TIMER_MANAGER
8418 vos_timer_exit();
8419#endif
8420#ifdef MEMORY_DEBUG
8421 vos_mem_exit();
8422#endif
8423
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008424#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008425 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008426#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008427 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8428 }
8429 else
8430 {
8431 //Send WLAN UP indication to Nlink Service
8432 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8433
8434 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008435 }
8436
8437 EXIT();
8438
8439 return ret_status;
8440}
8441
Jeff Johnson32d95a32012-09-10 13:15:23 -07008442/**---------------------------------------------------------------------------
8443
8444 \brief hdd_module_init() - Init Function
8445
8446 This is the driver entry point (invoked when module is loaded using insmod)
8447
8448 \param - None
8449
8450 \return - 0 for success, non zero for failure
8451
8452 --------------------------------------------------------------------------*/
8453#ifdef MODULE
8454static int __init hdd_module_init ( void)
8455{
8456 return hdd_driver_init();
8457}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008458#else /* #ifdef MODULE */
8459static int __init hdd_module_init ( void)
8460{
8461 /* Driver initialization is delayed to fwpath_changed_handler */
8462 return 0;
8463}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008464#endif /* #ifdef MODULE */
8465
Jeff Johnson295189b2012-06-20 16:38:30 -07008466
8467/**---------------------------------------------------------------------------
8468
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008469 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008470
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008471 This is the driver exit point (invoked when module is unloaded using rmmod
8472 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008473
8474 \param - None
8475
8476 \return - None
8477
8478 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008479static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008480{
8481 hdd_context_t *pHddCtx = NULL;
8482 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008483 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008484
8485 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8486
8487 //Get the global vos context
8488 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8489
8490 if(!pVosContext)
8491 {
8492 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8493 goto done;
8494 }
8495
8496 //Get the HDD context.
8497 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8498
8499 if(!pHddCtx)
8500 {
8501 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8502 }
8503 else
8504 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008505 while(isWDresetInProgress()) {
8506 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8507 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008508 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008509
8510 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8511 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8512 "%s:SSR never completed, fatal error", __func__);
8513 VOS_BUG(0);
8514 }
8515 }
8516
Jeff Johnson295189b2012-06-20 16:38:30 -07008517
8518 pHddCtx->isLoadUnloadInProgress = TRUE;
8519 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8520
8521 //Do all the cleanup before deregistering the driver
8522 hdd_wlan_exit(pHddCtx);
8523 }
8524
Jeff Johnson295189b2012-06-20 16:38:30 -07008525 vos_preClose( &pVosContext );
8526
8527#ifdef TIMER_MANAGER
8528 vos_timer_exit();
8529#endif
8530#ifdef MEMORY_DEBUG
8531 vos_mem_exit();
8532#endif
8533
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308534#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8535 vos_wconn_trace_exit();
8536#endif
8537
Jeff Johnson295189b2012-06-20 16:38:30 -07008538done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008539#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008540 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008541#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008542 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8543}
8544
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008545/**---------------------------------------------------------------------------
8546
8547 \brief hdd_module_exit() - Exit function
8548
8549 This is the driver exit point (invoked when module is unloaded using rmmod)
8550
8551 \param - None
8552
8553 \return - None
8554
8555 --------------------------------------------------------------------------*/
8556static void __exit hdd_module_exit(void)
8557{
8558 hdd_driver_exit();
8559}
8560
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008561#ifdef MODULE
8562static int fwpath_changed_handler(const char *kmessage,
8563 struct kernel_param *kp)
8564{
Jeff Johnson76052702013-04-16 13:55:05 -07008565 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008566}
8567
8568static int con_mode_handler(const char *kmessage,
8569 struct kernel_param *kp)
8570{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008571 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008572}
8573#else /* #ifdef MODULE */
8574/**---------------------------------------------------------------------------
8575
Jeff Johnson76052702013-04-16 13:55:05 -07008576 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008577
Jeff Johnson76052702013-04-16 13:55:05 -07008578 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008579 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008580 - invoked when module parameter fwpath is modified from userspace to signal
8581 initializing the WLAN driver or when con_mode is modified from userspace
8582 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008583
8584 \return - 0 for success, non zero for failure
8585
8586 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008587static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008588{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008589 int ret_status;
8590
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008591 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008592 ret_status = hdd_driver_init();
8593 wlan_hdd_inited = ret_status ? 0 : 1;
8594 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008595 }
8596
8597 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008598
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008599 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008600
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008601 ret_status = hdd_driver_init();
8602 wlan_hdd_inited = ret_status ? 0 : 1;
8603 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008604}
8605
Jeff Johnson295189b2012-06-20 16:38:30 -07008606/**---------------------------------------------------------------------------
8607
Jeff Johnson76052702013-04-16 13:55:05 -07008608 \brief fwpath_changed_handler() - Handler Function
8609
8610 Handle changes to the fwpath parameter
8611
8612 \return - 0 for success, non zero for failure
8613
8614 --------------------------------------------------------------------------*/
8615static int fwpath_changed_handler(const char *kmessage,
8616 struct kernel_param *kp)
8617{
8618 int ret;
8619
8620 ret = param_set_copystring(kmessage, kp);
8621 if (0 == ret)
8622 ret = kickstart_driver();
8623 return ret;
8624}
8625
8626/**---------------------------------------------------------------------------
8627
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008628 \brief con_mode_handler() -
8629
8630 Handler function for module param con_mode when it is changed by userspace
8631 Dynamically linked - do nothing
8632 Statically linked - exit and init driver, as in rmmod and insmod
8633
Jeff Johnson76052702013-04-16 13:55:05 -07008634 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008635
Jeff Johnson76052702013-04-16 13:55:05 -07008636 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008637
8638 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008639static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008640{
Jeff Johnson76052702013-04-16 13:55:05 -07008641 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008642
Jeff Johnson76052702013-04-16 13:55:05 -07008643 ret = param_set_int(kmessage, kp);
8644 if (0 == ret)
8645 ret = kickstart_driver();
8646 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008647}
8648#endif /* #ifdef MODULE */
8649
8650/**---------------------------------------------------------------------------
8651
Jeff Johnson295189b2012-06-20 16:38:30 -07008652 \brief hdd_get_conparam() -
8653
8654 This is the driver exit point (invoked when module is unloaded using rmmod)
8655
8656 \param - None
8657
8658 \return - tVOS_CON_MODE
8659
8660 --------------------------------------------------------------------------*/
8661tVOS_CON_MODE hdd_get_conparam ( void )
8662{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008663#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008664 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008665#else
8666 return (tVOS_CON_MODE)curr_con_mode;
8667#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008668}
8669void hdd_set_conparam ( v_UINT_t newParam )
8670{
8671 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008672#ifndef MODULE
8673 curr_con_mode = con_mode;
8674#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008675}
8676/**---------------------------------------------------------------------------
8677
8678 \brief hdd_softap_sta_deauth() - function
8679
8680 This to take counter measure to handle deauth req from HDD
8681
8682 \param - pAdapter - Pointer to the HDD
8683
8684 \param - enable - boolean value
8685
8686 \return - None
8687
8688 --------------------------------------------------------------------------*/
8689
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008690VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008691{
Jeff Johnson295189b2012-06-20 16:38:30 -07008692 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008693 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008694
8695 ENTER();
8696
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008697 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8698 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008699
8700 //Ignore request to deauth bcmc station
8701 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008702 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008703
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008704 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008705
8706 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008707 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008708}
8709
8710/**---------------------------------------------------------------------------
8711
8712 \brief hdd_softap_sta_disassoc() - function
8713
8714 This to take counter measure to handle deauth req from HDD
8715
8716 \param - pAdapter - Pointer to the HDD
8717
8718 \param - enable - boolean value
8719
8720 \return - None
8721
8722 --------------------------------------------------------------------------*/
8723
8724void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8725{
8726 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8727
8728 ENTER();
8729
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308730 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008731
8732 //Ignore request to disassoc bcmc station
8733 if( pDestMacAddress[0] & 0x1 )
8734 return;
8735
8736 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8737}
8738
8739void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8740{
8741 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8742
8743 ENTER();
8744
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308745 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008746
8747 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8748}
8749
Jeff Johnson295189b2012-06-20 16:38:30 -07008750/**---------------------------------------------------------------------------
8751 *
8752 * \brief hdd_get__concurrency_mode() -
8753 *
8754 *
8755 * \param - None
8756 *
8757 * \return - CONCURRENCY MODE
8758 *
8759 * --------------------------------------------------------------------------*/
8760tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8761{
8762 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8763 hdd_context_t *pHddCtx;
8764
8765 if (NULL != pVosContext)
8766 {
8767 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8768 if (NULL != pHddCtx)
8769 {
8770 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8771 }
8772 }
8773
8774 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008775 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008776 return VOS_STA;
8777}
8778
8779/* Decide whether to allow/not the apps power collapse.
8780 * Allow apps power collapse if we are in connected state.
8781 * if not, allow only if we are in IMPS */
8782v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8783{
8784 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008785 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008786 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008787 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8788 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8789 hdd_adapter_t *pAdapter = NULL;
8790 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008791 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008792
Jeff Johnson295189b2012-06-20 16:38:30 -07008793 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8794 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008795
Yathish9f22e662012-12-10 14:21:35 -08008796 concurrent_state = hdd_get_concurrency_mode();
8797
8798#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8799 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8800 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8801 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8802 return TRUE;
8803#endif
8804
Jeff Johnson295189b2012-06-20 16:38:30 -07008805 /*loop through all adapters. TBD fix for Concurrency */
8806 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8807 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8808 {
8809 pAdapter = pAdapterNode->pAdapter;
8810 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8811 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8812 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008813 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008814 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008815 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008816 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8817 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008818 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008819 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008820 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8821 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008822 return FALSE;
8823 }
8824 }
8825 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8826 pAdapterNode = pNext;
8827 }
8828 return TRUE;
8829}
8830
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008831/* Decides whether to send suspend notification to Riva
8832 * if any adapter is in BMPS; then it is required */
8833v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8834{
8835 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8836 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8837
8838 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8839 {
8840 return TRUE;
8841 }
8842 return FALSE;
8843}
8844
Jeff Johnson295189b2012-06-20 16:38:30 -07008845void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8846{
8847 switch(mode)
8848 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008849 case VOS_STA_MODE:
8850 case VOS_P2P_CLIENT_MODE:
8851 case VOS_P2P_GO_MODE:
8852 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008853 pHddCtx->concurrency_mode |= (1 << mode);
8854 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008855 break;
8856 default:
8857 break;
8858
8859 }
8860 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8861 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8862}
8863
8864
8865void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8866{
8867 switch(mode)
8868 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008869 case VOS_STA_MODE:
8870 case VOS_P2P_CLIENT_MODE:
8871 case VOS_P2P_GO_MODE:
8872 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008873 pHddCtx->no_of_sessions[mode]--;
8874 if (!(pHddCtx->no_of_sessions[mode]))
8875 pHddCtx->concurrency_mode &= (~(1 << mode));
8876 break;
8877 default:
8878 break;
8879 }
8880 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8881 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8882}
8883
Jeff Johnsone7245742012-09-05 17:12:55 -07008884/**---------------------------------------------------------------------------
8885 *
8886 * \brief wlan_hdd_restart_init
8887 *
8888 * This function initalizes restart timer/flag. An internal function.
8889 *
8890 * \param - pHddCtx
8891 *
8892 * \return - None
8893 *
8894 * --------------------------------------------------------------------------*/
8895
8896static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8897{
8898 /* Initialize */
8899 pHddCtx->hdd_restart_retries = 0;
8900 atomic_set(&pHddCtx->isRestartInProgress, 0);
8901 vos_timer_init(&pHddCtx->hdd_restart_timer,
8902 VOS_TIMER_TYPE_SW,
8903 wlan_hdd_restart_timer_cb,
8904 pHddCtx);
8905}
8906/**---------------------------------------------------------------------------
8907 *
8908 * \brief wlan_hdd_restart_deinit
8909 *
8910 * This function cleans up the resources used. An internal function.
8911 *
8912 * \param - pHddCtx
8913 *
8914 * \return - None
8915 *
8916 * --------------------------------------------------------------------------*/
8917
8918static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8919{
8920
8921 VOS_STATUS vos_status;
8922 /* Block any further calls */
8923 atomic_set(&pHddCtx->isRestartInProgress, 1);
8924 /* Cleanup */
8925 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8926 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008927 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008928 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8929 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008930 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008931
8932}
8933
8934/**---------------------------------------------------------------------------
8935 *
8936 * \brief wlan_hdd_framework_restart
8937 *
8938 * This function uses a cfg80211 API to start a framework initiated WLAN
8939 * driver module unload/load.
8940 *
8941 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8942 *
8943 *
8944 * \param - pHddCtx
8945 *
8946 * \return - VOS_STATUS_SUCCESS: Success
8947 * VOS_STATUS_E_EMPTY: Adapter is Empty
8948 * VOS_STATUS_E_NOMEM: No memory
8949
8950 * --------------------------------------------------------------------------*/
8951
8952static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8953{
8954 VOS_STATUS status = VOS_STATUS_SUCCESS;
8955 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008956 int len = (sizeof (struct ieee80211_mgmt));
8957 struct ieee80211_mgmt *mgmt = NULL;
8958
8959 /* Prepare the DEAUTH managment frame with reason code */
8960 mgmt = kzalloc(len, GFP_KERNEL);
8961 if(mgmt == NULL)
8962 {
8963 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8964 "%s: memory allocation failed (%d bytes)", __func__, len);
8965 return VOS_STATUS_E_NOMEM;
8966 }
8967 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008968
8969 /* Iterate over all adapters/devices */
8970 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8971 do
8972 {
8973 if( (status == VOS_STATUS_SUCCESS) &&
8974 pAdapterNode &&
8975 pAdapterNode->pAdapter)
8976 {
8977 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8978 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8979 pAdapterNode->pAdapter->dev->name,
8980 pAdapterNode->pAdapter->device_mode,
8981 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008982 /*
8983 * CFG80211 event to restart the driver
8984 *
8985 * 'cfg80211_send_unprot_deauth' sends a
8986 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8987 * of SME(Linux Kernel) state machine.
8988 *
8989 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8990 * the driver.
8991 *
8992 */
8993
8994 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008995 }
8996 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8997 pAdapterNode = pNext;
8998 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8999
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009000
9001 /* Free the allocated management frame */
9002 kfree(mgmt);
9003
Jeff Johnsone7245742012-09-05 17:12:55 -07009004 /* Retry until we unload or reach max count */
9005 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9006 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9007
9008 return status;
9009
9010}
9011/**---------------------------------------------------------------------------
9012 *
9013 * \brief wlan_hdd_restart_timer_cb
9014 *
9015 * Restart timer callback. An internal function.
9016 *
9017 * \param - User data:
9018 *
9019 * \return - None
9020 *
9021 * --------------------------------------------------------------------------*/
9022
9023void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9024{
9025 hdd_context_t *pHddCtx = usrDataForCallback;
9026 wlan_hdd_framework_restart(pHddCtx);
9027 return;
9028
9029}
9030
9031
9032/**---------------------------------------------------------------------------
9033 *
9034 * \brief wlan_hdd_restart_driver
9035 *
9036 * This function sends an event to supplicant to restart the WLAN driver.
9037 *
9038 * This function is called from vos_wlanRestart.
9039 *
9040 * \param - pHddCtx
9041 *
9042 * \return - VOS_STATUS_SUCCESS: Success
9043 * VOS_STATUS_E_EMPTY: Adapter is Empty
9044 * VOS_STATUS_E_ALREADY: Request already in progress
9045
9046 * --------------------------------------------------------------------------*/
9047VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9048{
9049 VOS_STATUS status = VOS_STATUS_SUCCESS;
9050
9051 /* A tight check to make sure reentrancy */
9052 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9053 {
9054 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9055 "%s: WLAN restart is already in progress", __func__);
9056
9057 return VOS_STATUS_E_ALREADY;
9058 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009059 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009060#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009061 wcnss_reset_intr();
9062#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009063
Jeff Johnsone7245742012-09-05 17:12:55 -07009064 return status;
9065}
9066
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009067/*
9068 * API to find if there is any STA or P2P-Client is connected
9069 */
9070VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9071{
9072 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9073}
Jeff Johnsone7245742012-09-05 17:12:55 -07009074
Jeff Johnson295189b2012-06-20 16:38:30 -07009075//Register the module init/exit functions
9076module_init(hdd_module_init);
9077module_exit(hdd_module_exit);
9078
9079MODULE_LICENSE("Dual BSD/GPL");
9080MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9081MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9082
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009083module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9084 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009085
Jeff Johnson76052702013-04-16 13:55:05 -07009086module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009087 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009088
9089module_param(enable_dfs_chan_scan, int,
9090 S_IRUSR | S_IRGRP | S_IROTH);
9091
9092module_param(enable_11d, int,
9093 S_IRUSR | S_IRGRP | S_IROTH);
9094
9095module_param(country_code, charp,
9096 S_IRUSR | S_IRGRP | S_IROTH);