blob: 21151e65823ba12f86beb6e3cba69182e763edd3 [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;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800817 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530818
819 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800820 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
821 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
822 nRtt = 0;
823 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530824
825 /*go to space after WLS_BATCHING_SET command*/
826 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
827 /*no argument after the command*/
828 if (NULL == inPtr)
829 {
830 return -EINVAL;
831 }
832
833 /*no space after the command*/
834 else if (SPACE_ASCII_VALUE != *inPtr)
835 {
836 return -EINVAL;
837 }
838
839 /*removing empty spaces*/
840 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
841
842 /*no argument followed by spaces*/
843 if ('\0' == *inPtr)
844 {
845 return -EINVAL;
846 }
847
848 /*check and parse SCANFREQ*/
849 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
850 {
851 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800852 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800853
Rajeev Kumarc933d982013-11-18 20:04:20 -0800854 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800855 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800856 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800857 }
858
Rajeev79dbe4c2013-10-05 11:03:42 +0530859 if ( (NULL == inPtr) || (TRUE == lastArg))
860 {
861 return -EINVAL;
862 }
863 }
864
865 /*check and parse MSCAN*/
866 if ((strncmp(inPtr, "MSCAN", 5) == 0))
867 {
868 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800869 &nMscan, &lastArg);
870
871 if (0 == nMscan)
872 {
873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
874 "invalid MSCAN=%d", nMscan);
875 return -EINVAL;
876 }
877
Rajeev79dbe4c2013-10-05 11:03:42 +0530878 if (TRUE == lastArg)
879 {
880 goto done;
881 }
882 else if (NULL == inPtr)
883 {
884 return -EINVAL;
885 }
886 }
887 else
888 {
889 return -EINVAL;
890 }
891
892 /*check and parse BESTN*/
893 if ((strncmp(inPtr, "BESTN", 5) == 0))
894 {
895 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800896 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800897
Rajeev Kumarc933d982013-11-18 20:04:20 -0800898 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800899 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800900 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800901 }
902
Rajeev79dbe4c2013-10-05 11:03:42 +0530903 if (TRUE == lastArg)
904 {
905 goto done;
906 }
907 else if (NULL == inPtr)
908 {
909 return -EINVAL;
910 }
911 }
912
913 /*check and parse CHANNEL*/
914 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
915 {
916 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800917
Rajeev79dbe4c2013-10-05 11:03:42 +0530918 if (('A' == val) || ('a' == val))
919 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800920 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530921 }
922 else if (('B' == val) || ('b' == val))
923 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800924 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530925 }
926 else
927 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800928 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
929 }
930
931 if (TRUE == lastArg)
932 {
933 goto done;
934 }
935 else if (NULL == inPtr)
936 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530937 return -EINVAL;
938 }
939 }
940
941 /*check and parse RTT*/
942 if ((strncmp(inPtr, "RTT", 3) == 0))
943 {
944 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800945 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530946 if (TRUE == lastArg)
947 {
948 goto done;
949 }
950 if (NULL == inPtr)
951 {
952 return -EINVAL;
953 }
954 }
955
956
957done:
958
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800959 pHddSetBatchScanReq->scanFrequency = nScanFreq;
960 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
961 pHddSetBatchScanReq->bestNetwork = nBestN;
962 pHddSetBatchScanReq->rfBand = ucRfBand;
963 pHddSetBatchScanReq->rtt = nRtt;
964
Rajeev79dbe4c2013-10-05 11:03:42 +0530965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
966 "Received WLS_BATCHING_SET with SCANFREQ=%d "
967 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
968 pHddSetBatchScanReq->scanFrequency,
969 pHddSetBatchScanReq->numberOfScansToBatch,
970 pHddSetBatchScanReq->bestNetwork,
971 pHddSetBatchScanReq->rfBand,
972 pHddSetBatchScanReq->rtt);
973
974 return 0;
975}/*End of hdd_parse_set_batchscan_command*/
976
977/**---------------------------------------------------------------------------
978
979 \brief hdd_set_batch_scan_req_callback () - This function is called after
980 receiving set batch scan response from FW and it saves set batch scan
981 response data FW to HDD context and sets the completion event on
982 which hdd_ioctl is waiting
983
984 \param - callbackContext Pointer to HDD adapter
985 \param - pRsp Pointer to set batch scan response data received from FW
986
987 \return - nothing
988
989 --------------------------------------------------------------------------*/
990static void hdd_set_batch_scan_req_callback
991(
992 void *callbackContext,
993 tSirSetBatchScanRsp *pRsp
994)
995{
996 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
997 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
998
999 /*sanity check*/
1000 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1001 {
1002 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1003 "%s: Invalid pAdapter magic", __func__);
1004 VOS_ASSERT(0);
1005 return;
1006 }
1007 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1008
1009 /*save set batch scan response*/
1010 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1011
1012 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1013 "Received set batch scan rsp from FW with nScansToBatch=%d",
1014 pHddSetBatchScanRsp->nScansToBatch);
1015
1016 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1017 complete(&pAdapter->hdd_set_batch_scan_req_var);
1018
1019 return;
1020}/*End of hdd_set_batch_scan_req_callback*/
1021
1022
1023/**---------------------------------------------------------------------------
1024
1025 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1026 info in hdd batch scan response queue
1027
1028 \param - pAdapter Pointer to hdd adapter
1029 \param - pAPMetaInfo Pointer to access point meta info
1030 \param - scanId scan ID of batch scan response
1031 \param - isLastAp tells whether AP is last AP in batch scan response or not
1032
1033 \return - nothing
1034
1035 --------------------------------------------------------------------------*/
1036static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1037 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1038{
1039 tHddBatchScanRsp *pHead;
1040 tHddBatchScanRsp *pNode;
1041 tHddBatchScanRsp *pPrev;
1042 tHddBatchScanRsp *pTemp;
1043 tANI_U8 ssidLen;
1044
1045 /*head of hdd batch scan response queue*/
1046 pHead = pAdapter->pBatchScanRsp;
1047
1048 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1049 if (NULL == pNode)
1050 {
1051 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1052 "%s: Could not allocate memory", __func__);
1053 VOS_ASSERT(0);
1054 return;
1055 }
1056
1057 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1058 sizeof(pNode->ApInfo.bssid));
1059 ssidLen = strlen(pApMetaInfo->ssid);
1060 if (SIR_MAX_SSID_SIZE < ssidLen)
1061 {
1062 /*invalid scan result*/
1063 vos_mem_free(pNode);
1064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1065 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1066 return;
1067 }
1068 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1069 /*null terminate ssid*/
1070 pNode->ApInfo.ssid[ssidLen] = '\0';
1071 pNode->ApInfo.ch = pApMetaInfo->ch;
1072 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1073 pNode->ApInfo.age = pApMetaInfo->timestamp;
1074 pNode->ApInfo.batchId = scanId;
1075 pNode->ApInfo.isLastAp = isLastAp;
1076
1077 pNode->pNext = NULL;
1078 if (NULL == pHead)
1079 {
1080 pAdapter->pBatchScanRsp = pNode;
1081 }
1082 else
1083 {
1084 pTemp = pHead;
1085 while (NULL != pTemp)
1086 {
1087 pPrev = pTemp;
1088 pTemp = pTemp->pNext;
1089 }
1090 pPrev->pNext = pNode;
1091 }
1092
1093 return;
1094}/*End of hdd_populate_batch_scan_rsp_queue*/
1095
1096/**---------------------------------------------------------------------------
1097
1098 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1099 receiving batch scan response indication from FW. It saves get batch scan
1100 response data in HDD batch scan response queue. This callback sets the
1101 completion event on which hdd_ioctl is waiting only after getting complete
1102 batch scan response data from FW
1103
1104 \param - callbackContext Pointer to HDD adapter
1105 \param - pRsp Pointer to get batch scan response data received from FW
1106
1107 \return - nothing
1108
1109 --------------------------------------------------------------------------*/
1110static void hdd_batch_scan_result_ind_callback
1111(
1112 void *callbackContext,
1113 void *pRsp
1114)
1115{
1116 v_BOOL_t isLastAp;
1117 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001118 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301119 tANI_U32 numberScanList;
1120 tANI_U32 nextScanListOffset;
1121 tANI_U32 nextApMetaInfoOffset;
1122 hdd_adapter_t* pAdapter;
1123 tpSirBatchScanList pScanList;
1124 tpSirBatchScanNetworkInfo pApMetaInfo;
1125 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1126 tSirSetBatchScanReq *pReq;
1127
1128 pAdapter = (hdd_adapter_t *)callbackContext;
1129 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001130 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301131 {
1132 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1133 "%s: Invalid pAdapter magic", __func__);
1134 VOS_ASSERT(0);
1135 return;
1136 }
1137
1138 /*initialize locals*/
1139 pReq = &pAdapter->hddSetBatchScanReq;
1140 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1141 isLastAp = FALSE;
1142 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001143 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301144 numberScanList = 0;
1145 nextScanListOffset = 0;
1146 nextApMetaInfoOffset = 0;
1147 pScanList = NULL;
1148 pApMetaInfo = NULL;
1149
1150 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1151 {
1152 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1153 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1154 isLastAp = TRUE;
1155 goto done;
1156 }
1157
1158 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1159 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1160 "Batch scan rsp: numberScalList %d", numberScanList);
1161
1162 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1163 {
1164 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1165 "%s: numberScanList %d", __func__, numberScanList);
1166 isLastAp = TRUE;
1167 goto done;
1168 }
1169
1170 while (numberScanList)
1171 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001172 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301173 nextScanListOffset);
1174 if (NULL == pScanList)
1175 {
1176 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1177 "%s: pScanList is %p", __func__, pScanList);
1178 isLastAp = TRUE;
1179 goto done;
1180 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001181 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301182 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001183 "Batch scan rsp: numApMetaInfo %d scanId %d",
1184 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301185
1186 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1187 {
1188 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1189 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1190 isLastAp = TRUE;
1191 goto done;
1192 }
1193
Rajeev Kumarce651e42013-10-21 18:57:15 -07001194 /*Initialize next AP meta info offset for next scan list*/
1195 nextApMetaInfoOffset = 0;
1196
Rajeev79dbe4c2013-10-05 11:03:42 +05301197 while (numApMetaInfo)
1198 {
1199 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1200 nextApMetaInfoOffset);
1201 if (NULL == pApMetaInfo)
1202 {
1203 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1204 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1205 isLastAp = TRUE;
1206 goto done;
1207 }
1208 /*calculate AP age*/
1209 pApMetaInfo->timestamp =
1210 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1211
1212 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001213 "%s: bssId "MAC_ADDRESS_STR
1214 " ch %d rssi %d timestamp %d", __func__,
1215 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1216 pApMetaInfo->ch, pApMetaInfo->rssi,
1217 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301218
1219 /*mark last AP in batch scan response*/
1220 if ((TRUE == pBatchScanRsp->isLastResult) &&
1221 (1 == numberScanList) && (1 == numApMetaInfo))
1222 {
1223 isLastAp = TRUE;
1224 }
1225
1226 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1227 /*store batch scan repsonse in hdd queue*/
1228 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1229 pScanList->scanId, isLastAp);
1230 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1231
1232 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1233 numApMetaInfo--;
1234 }
1235
Rajeev Kumarce651e42013-10-21 18:57:15 -07001236 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1237 + (sizeof(tSirBatchScanNetworkInfo)
1238 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301239 numberScanList--;
1240 }
1241
1242done:
1243
1244 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1245 requested from hdd_ioctl*/
1246 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1247 (TRUE == isLastAp))
1248 {
1249 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1250 complete(&pAdapter->hdd_get_batch_scan_req_var);
1251 }
1252
1253 return;
1254}/*End of hdd_batch_scan_result_ind_callback*/
1255
1256/**---------------------------------------------------------------------------
1257
1258 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1259 response as per batch scan FR request format by putting proper markers
1260
1261 \param - pDest pointer to destination buffer
1262 \param - cur_len current length
1263 \param - tot_len total remaining size which can be written to user space
1264 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1265 \param - pAdapter Pointer to HDD adapter
1266
1267 \return - ret no of characters written
1268
1269 --------------------------------------------------------------------------*/
1270static tANI_U32
1271hdd_format_batch_scan_rsp
1272(
1273 tANI_U8 *pDest,
1274 tANI_U32 cur_len,
1275 tANI_U32 tot_len,
1276 tHddBatchScanRsp *pApMetaInfo,
1277 hdd_adapter_t* pAdapter
1278)
1279{
1280 tANI_U32 ret = 0;
1281 tANI_U32 rem_len = 0;
1282 tANI_U8 temp_len = 0;
1283 tANI_U8 temp_total_len = 0;
1284 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1285 tANI_U8 *pTemp = temp;
1286
1287 /*Batch scan reponse needs to be returned to user space in
1288 following format:
1289 "scancount=X\n" where X is the number of scans in current batch
1290 batch
1291 "trunc\n" optional present if current scan truncated
1292 "bssid=XX:XX:XX:XX:XX:XX\n"
1293 "ssid=XXXX\n"
1294 "freq=X\n" frequency in Mhz
1295 "level=XX\n"
1296 "age=X\n" ms
1297 "dist=X\n" cm (-1 if not available)
1298 "errror=X\n" (-1if not available)
1299 "====\n" (end of ap marker)
1300 "####\n" (end of scan marker)
1301 "----\n" (end of results)*/
1302 /*send scan result in above format to user space based on
1303 available length*/
1304 /*The GET response may have more data than the driver can return in its
1305 buffer. In that case the buffer should be filled to the nearest complete
1306 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1307 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1308 The final buffer should end with "----\n"*/
1309
1310 /*sanity*/
1311 if (cur_len > tot_len)
1312 {
1313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1314 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1315 return 0;
1316 }
1317 else
1318 {
1319 rem_len = (tot_len - cur_len);
1320 }
1321
1322 /*end scan marker*/
1323 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1324 {
1325 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1326 pTemp += temp_len;
1327 temp_total_len += temp_len;
1328 }
1329
1330 /*bssid*/
1331 temp_len = snprintf(pTemp, sizeof(temp),
1332 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1333 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1334 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1335 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1336 pTemp += temp_len;
1337 temp_total_len += temp_len;
1338
1339 /*ssid*/
1340 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1341 pApMetaInfo->ApInfo.ssid);
1342 pTemp += temp_len;
1343 temp_total_len += temp_len;
1344
1345 /*freq*/
1346 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001347 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301348 pTemp += temp_len;
1349 temp_total_len += temp_len;
1350
1351 /*level*/
1352 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1353 pApMetaInfo->ApInfo.rssi);
1354 pTemp += temp_len;
1355 temp_total_len += temp_len;
1356
1357 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001358 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301359 pApMetaInfo->ApInfo.age);
1360 pTemp += temp_len;
1361 temp_total_len += temp_len;
1362
1363 /*dist*/
1364 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1365 pTemp += temp_len;
1366 temp_total_len += temp_len;
1367
1368 /*error*/
1369 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1370 pTemp += temp_len;
1371 temp_total_len += temp_len;
1372
1373 /*end AP marker*/
1374 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1375 pTemp += temp_len;
1376 temp_total_len += temp_len;
1377
1378 /*last AP in batch scan response*/
1379 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1380 {
1381 /*end scan marker*/
1382 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1383 pTemp += temp_len;
1384 temp_total_len += temp_len;
1385
1386 /*end batch scan result marker*/
1387 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1388 pTemp += temp_len;
1389 temp_total_len += temp_len;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08001390
1391 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301392 }
1393
1394 if (temp_total_len < rem_len)
1395 {
1396 ret = temp_total_len + 1;
1397 strlcpy(pDest, temp, ret);
1398 pAdapter->isTruncated = FALSE;
1399 }
1400 else
1401 {
1402 pAdapter->isTruncated = TRUE;
1403 if (rem_len >= strlen("%%%%"))
1404 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001405 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301406 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001407 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301408 {
1409 ret = 0;
1410 }
1411 }
1412
1413 return ret;
1414
1415}/*End of hdd_format_batch_scan_rsp*/
1416
1417/**---------------------------------------------------------------------------
1418
1419 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1420 buffer starting with head of hdd batch scan response queue
1421
1422 \param - pAdapter Pointer to HDD adapter
1423 \param - pDest Pointer to user data buffer
1424 \param - cur_len current offset in user buffer
1425 \param - rem_len remaining no of bytes in user buffer
1426
1427 \return - number of bytes written in user buffer
1428
1429 --------------------------------------------------------------------------*/
1430
1431tANI_U32 hdd_populate_user_batch_scan_rsp
1432(
1433 hdd_adapter_t* pAdapter,
1434 tANI_U8 *pDest,
1435 tANI_U32 cur_len,
1436 tANI_U32 rem_len
1437)
1438{
1439 tHddBatchScanRsp *pHead;
1440 tHddBatchScanRsp *pPrev;
1441 tANI_U32 len;
1442
Rajeev79dbe4c2013-10-05 11:03:42 +05301443 pAdapter->isTruncated = FALSE;
1444
1445 /*head of hdd batch scan response queue*/
1446 pHead = pAdapter->pBatchScanRsp;
1447 while (pHead)
1448 {
1449 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1450 pAdapter);
1451 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001452 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301453 cur_len += len;
1454 if(TRUE == pAdapter->isTruncated)
1455 {
1456 /*result is truncated return rest of scan rsp in next req*/
1457 cur_len = rem_len;
1458 break;
1459 }
1460 pPrev = pHead;
1461 pHead = pHead->pNext;
1462 pAdapter->pBatchScanRsp = pHead;
1463 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1464 vos_mem_free(pPrev);
1465 }
1466
1467 return cur_len;
1468}/*End of hdd_populate_user_batch_scan_rsp*/
1469
1470/**---------------------------------------------------------------------------
1471
1472 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1473 scan response data from HDD queue to user space
1474 It does following in detail:
1475 a) if HDD has enough data in its queue then it 1st copies data to user
1476 space and then send get batch scan indication message to FW. In this
1477 case it does not wait on any event and batch scan response data will
1478 be populated in HDD response queue in MC thread context after receiving
1479 indication from FW
1480 b) else send get batch scan indication message to FW and wait on an event
1481 which will be set once HDD receives complete batch scan response from
1482 FW and then this function returns batch scan response to user space
1483
1484 \param - pAdapter Pointer to HDD adapter
1485 \param - pPrivData Pointer to priv_data
1486
1487 \return - 0 for success -EFAULT for failure
1488
1489 --------------------------------------------------------------------------*/
1490
1491int hdd_return_batch_scan_rsp_to_user
1492(
1493 hdd_adapter_t* pAdapter,
1494 hdd_priv_data_t *pPrivData,
1495 tANI_U8 *command
1496)
1497{
1498 tANI_U8 *pDest;
1499 tANI_U32 count = 0;
1500 tANI_U32 len = 0;
1501 tANI_U32 cur_len = 0;
1502 tANI_U32 rem_len = 0;
1503 eHalStatus halStatus;
1504 unsigned long rc;
1505 tSirTriggerBatchScanResultInd *pReq;
1506
1507 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1508 pReq->param = 0;/*batch scan client*/
1509 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1510 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1511
1512 cur_len = pPrivData->used_len;
1513 if (pPrivData->total_len > pPrivData->used_len)
1514 {
1515 rem_len = pPrivData->total_len - pPrivData->used_len;
1516 }
1517 else
1518 {
1519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1520 "%s: Invalid user data buffer total_len %d used_len %d",
1521 __func__, pPrivData->total_len, pPrivData->used_len);
1522 return -EFAULT;
1523 }
1524
1525 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1526 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1527 cur_len, rem_len);
1528 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1529
1530 /*enough scan result available in cache to return to user space or
1531 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001532 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301533 {
1534 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1535 halStatus = sme_TriggerBatchScanResultInd(
1536 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1537 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1538 pAdapter);
1539 if ( eHAL_STATUS_SUCCESS == halStatus )
1540 {
1541 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1542 {
1543 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1544 rc = wait_for_completion_timeout(
1545 &pAdapter->hdd_get_batch_scan_req_var,
1546 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1547 if (0 == rc)
1548 {
1549 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1550 "%s: Timeout waiting to fetch batch scan rsp from fw",
1551 __func__);
1552 return -EFAULT;
1553 }
1554 }
1555
1556 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001557 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301558 pDest += len;
1559 cur_len += len;
1560
1561 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1562 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1563 cur_len, rem_len);
1564 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1565
1566 count = 0;
1567 len = (len - pPrivData->used_len);
1568 pDest = (command + pPrivData->used_len);
1569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001570 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301571 while(count < len)
1572 {
1573 printk("%c", *(pDest + count));
1574 count++;
1575 }
1576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1577 "%s: copy %d data to user buffer", __func__, len);
1578 if (copy_to_user(pPrivData->buf, pDest, len))
1579 {
1580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1581 "%s: failed to copy data to user buffer", __func__);
1582 return -EFAULT;
1583 }
1584 }
1585 else
1586 {
1587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1588 "sme_GetBatchScanScan returned failure halStatus %d",
1589 halStatus);
1590 return -EINVAL;
1591 }
1592 }
1593 else
1594 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301595 count = 0;
1596 len = (len - pPrivData->used_len);
1597 pDest = (command + pPrivData->used_len);
1598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001599 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301600 while(count < len)
1601 {
1602 printk("%c", *(pDest + count));
1603 count++;
1604 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001605 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1606 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301607 if (copy_to_user(pPrivData->buf, pDest, len))
1608 {
1609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1610 "%s: failed to copy data to user buffer", __func__);
1611 return -EFAULT;
1612 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301613 }
1614
1615 return 0;
1616} /*End of hdd_return_batch_scan_rsp_to_user*/
1617
1618#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1619
Jeff Johnson295189b2012-06-20 16:38:30 -07001620int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1621{
1622 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1623 hdd_priv_data_t priv_data;
1624 tANI_U8 *command = NULL;
1625 int ret = 0;
1626
1627 if (NULL == pAdapter)
1628 {
1629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001630 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001631 ret = -ENODEV;
1632 goto exit;
1633 }
1634
Jeff Johnsone7245742012-09-05 17:12:55 -07001635 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001636 {
1637 ret = -EINVAL;
1638 goto exit;
1639 }
1640
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001641 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1642 {
1643 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1644 "%s:LOGP in Progress. Ignore!!!", __func__);
1645 ret = -EBUSY;
1646 goto exit;
1647 }
1648
Jeff Johnson295189b2012-06-20 16:38:30 -07001649 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1650 {
1651 ret = -EFAULT;
1652 goto exit;
1653 }
1654
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001655 if (priv_data.total_len <= 0)
1656 {
1657 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1658 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1659 priv_data.total_len);
1660 ret = -EINVAL;
1661 goto exit;
1662 }
1663
1664 /* Allocate +1 for '\0' */
1665 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001666 if (!command)
1667 {
1668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001669 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001670 ret = -ENOMEM;
1671 goto exit;
1672 }
1673
1674 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1675 {
1676 ret = -EFAULT;
1677 goto exit;
1678 }
1679
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001680 /* Making sure the command is NUL-terminated */
1681 command[priv_data.total_len] = '\0';
1682
Jeff Johnson295189b2012-06-20 16:38:30 -07001683 if ((SIOCDEVPRIVATE + 1) == cmd)
1684 {
1685 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1686
1687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001688 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001689
1690 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1691 {
1692 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1693 sizeof(tSirMacAddr)))
1694 {
1695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001696 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001697 ret = -EFAULT;
1698 }
1699 }
Amar Singhal0974e402013-02-12 14:27:46 -08001700 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001701 {
Amar Singhal0974e402013-02-12 14:27:46 -08001702 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001703 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001704
Jeff Johnson295189b2012-06-20 16:38:30 -07001705 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001706
1707 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001708 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001709 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001710 "%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 -07001711 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001712 ret = hdd_setBand_helper(dev, ptr);
1713 }
Kiet Lamf040f472013-11-20 21:15:23 +05301714 else if(strncmp(command, "SETWMMPS", 8) == 0)
1715 {
1716 tANI_U8 *ptr = command;
1717 ret = hdd_wmmps_helper(pAdapter, ptr);
1718 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001719 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1720 {
1721 char *country_code;
1722
1723 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001724
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001725 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001726 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001727#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301728 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001729#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001730 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1731 (void *)(tSmeChangeCountryCallback)
1732 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05301733 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001734 if (eHAL_STATUS_SUCCESS == ret)
1735 {
1736 ret = wait_for_completion_interruptible_timeout(
1737 &pAdapter->change_country_code,
1738 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1739 if (0 >= ret)
1740 {
1741 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1742 __func__);
1743 }
1744 }
1745 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001746 {
1747 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001748 "%s: SME Change Country code fail ret=%d", __func__, ret);
1749 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001750 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001751
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001752 }
1753 /*
1754 command should be a string having format
1755 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1756 */
Amar Singhal0974e402013-02-12 14:27:46 -08001757 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001758 {
Amar Singhal0974e402013-02-12 14:27:46 -08001759 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001760
1761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001762 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001763
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001764 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001765 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001766 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1767 {
1768 int suspend = 0;
1769 tANI_U8 *ptr = (tANI_U8*)command + 15;
1770
1771 suspend = *ptr - '0';
1772 hdd_set_wlan_suspend_mode(suspend);
1773 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001774#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1775 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1776 {
1777 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001778 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001779 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1780 eHalStatus status = eHAL_STATUS_SUCCESS;
1781
1782 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1783 value = value + 15;
1784
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001785 /* Convert the value from ascii to integer */
1786 ret = kstrtos8(value, 10, &rssi);
1787 if (ret < 0)
1788 {
1789 /* If the input value is greater than max value of datatype, then also
1790 kstrtou8 fails */
1791 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1792 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001793 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001794 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1795 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1796 ret = -EINVAL;
1797 goto exit;
1798 }
1799
Srinivas Girigowdade697412013-02-14 16:31:48 -08001800 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001801
Srinivas Girigowdade697412013-02-14 16:31:48 -08001802 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1803 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1804 {
1805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1806 "Neighbor lookup threshold value %d is out of range"
1807 " (Min: %d Max: %d)", lookUpThreshold,
1808 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1809 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1810 ret = -EINVAL;
1811 goto exit;
1812 }
1813
1814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1815 "%s: Received Command to Set Roam trigger"
1816 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1817
1818 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1819 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1820 if (eHAL_STATUS_SUCCESS != status)
1821 {
1822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1823 "%s: Failed to set roam trigger, try again", __func__);
1824 ret = -EPERM;
1825 goto exit;
1826 }
1827
1828 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1829 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1830 }
1831 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1832 {
1833 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1834 int rssi = (-1) * lookUpThreshold;
1835 char extra[32];
1836 tANI_U8 len = 0;
1837
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001838 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001839 if (copy_to_user(priv_data.buf, &extra, len + 1))
1840 {
1841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1842 "%s: failed to copy data to user buffer", __func__);
1843 ret = -EFAULT;
1844 goto exit;
1845 }
1846 }
1847 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1848 {
1849 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001850 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001851 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001852
Srinivas Girigowdade697412013-02-14 16:31:48 -08001853 /* input refresh period is in terms of seconds */
1854 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1855 value = value + 18;
1856 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001857 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001858 if (ret < 0)
1859 {
1860 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001861 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001863 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001864 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001865 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1866 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001867 ret = -EINVAL;
1868 goto exit;
1869 }
1870
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001871 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1872 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001873 {
1874 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001875 "Roam scan period value %d is out of range"
1876 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001877 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1878 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001879 ret = -EINVAL;
1880 goto exit;
1881 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001882 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001883
1884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1885 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001886 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001887
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001888 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1889 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001890 }
1891 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1892 {
1893 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1894 char extra[32];
1895 tANI_U8 len = 0;
1896
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001897 len = scnprintf(extra, sizeof(extra), "%s %d",
1898 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001899 /* Returned value is in units of seconds */
1900 if (copy_to_user(priv_data.buf, &extra, len + 1))
1901 {
1902 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1903 "%s: failed to copy data to user buffer", __func__);
1904 ret = -EFAULT;
1905 goto exit;
1906 }
1907 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001908 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1909 {
1910 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001911 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001912 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001913
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001914 /* input refresh period is in terms of seconds */
1915 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1916 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001917
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001918 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001919 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001920 if (ret < 0)
1921 {
1922 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001923 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001924 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001925 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001926 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001927 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1928 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1929 ret = -EINVAL;
1930 goto exit;
1931 }
1932
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001933 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1934 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1935 {
1936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1937 "Neighbor scan results refresh period value %d is out of range"
1938 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1939 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1940 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1941 ret = -EINVAL;
1942 goto exit;
1943 }
1944 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1945
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001946 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1947 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001948 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001949
1950 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1951 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1952 }
1953 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1954 {
1955 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1956 char extra[32];
1957 tANI_U8 len = 0;
1958
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001959 len = scnprintf(extra, sizeof(extra), "%s %d",
1960 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001961 /* Returned value is in units of seconds */
1962 if (copy_to_user(priv_data.buf, &extra, len + 1))
1963 {
1964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1965 "%s: failed to copy data to user buffer", __func__);
1966 ret = -EFAULT;
1967 goto exit;
1968 }
1969 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001970#ifdef FEATURE_WLAN_LFR
1971 /* SETROAMMODE */
1972 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1973 {
1974 tANI_U8 *value = command;
1975 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1976
1977 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1978 value = value + SIZE_OF_SETROAMMODE + 1;
1979
1980 /* Convert the value from ascii to integer */
1981 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1982 if (ret < 0)
1983 {
1984 /* If the input value is greater than max value of datatype, then also
1985 kstrtou8 fails */
1986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1987 "%s: kstrtou8 failed range [%d - %d]", __func__,
1988 CFG_LFR_FEATURE_ENABLED_MIN,
1989 CFG_LFR_FEATURE_ENABLED_MAX);
1990 ret = -EINVAL;
1991 goto exit;
1992 }
1993 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1994 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1995 {
1996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1997 "Roam Mode value %d is out of range"
1998 " (Min: %d Max: %d)", roamMode,
1999 CFG_LFR_FEATURE_ENABLED_MIN,
2000 CFG_LFR_FEATURE_ENABLED_MAX);
2001 ret = -EINVAL;
2002 goto exit;
2003 }
2004
2005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2006 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2007 /*
2008 * Note that
2009 * SETROAMMODE 0 is to enable LFR while
2010 * SETROAMMODE 1 is to disable LFR, but
2011 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2012 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2013 */
2014 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2015 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2016 else
2017 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2018
2019 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2020 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2021 }
2022 /* GETROAMMODE */
2023 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2024 {
2025 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2026 char extra[32];
2027 tANI_U8 len = 0;
2028
2029 /*
2030 * roamMode value shall be inverted because the sementics is different.
2031 */
2032 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2033 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2034 else
2035 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2036
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002037 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002038 if (copy_to_user(priv_data.buf, &extra, len + 1))
2039 {
2040 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2041 "%s: failed to copy data to user buffer", __func__);
2042 ret = -EFAULT;
2043 goto exit;
2044 }
2045 }
2046#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002047#endif
2048#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2049 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2050 {
2051 tANI_U8 *value = command;
2052 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2053
2054 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2055 value = value + 13;
2056 /* Convert the value from ascii to integer */
2057 ret = kstrtou8(value, 10, &roamRssiDiff);
2058 if (ret < 0)
2059 {
2060 /* If the input value is greater than max value of datatype, then also
2061 kstrtou8 fails */
2062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2063 "%s: kstrtou8 failed range [%d - %d]", __func__,
2064 CFG_ROAM_RSSI_DIFF_MIN,
2065 CFG_ROAM_RSSI_DIFF_MAX);
2066 ret = -EINVAL;
2067 goto exit;
2068 }
2069
2070 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2071 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2072 {
2073 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2074 "Roam rssi diff value %d is out of range"
2075 " (Min: %d Max: %d)", roamRssiDiff,
2076 CFG_ROAM_RSSI_DIFF_MIN,
2077 CFG_ROAM_RSSI_DIFF_MAX);
2078 ret = -EINVAL;
2079 goto exit;
2080 }
2081
2082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2083 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2084
2085 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2086 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2087 }
2088 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2089 {
2090 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2091 char extra[32];
2092 tANI_U8 len = 0;
2093
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002094 len = scnprintf(extra, sizeof(extra), "%s %d",
2095 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002096 if (copy_to_user(priv_data.buf, &extra, len + 1))
2097 {
2098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2099 "%s: failed to copy data to user buffer", __func__);
2100 ret = -EFAULT;
2101 goto exit;
2102 }
2103 }
2104#endif
2105#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2106 else if (strncmp(command, "GETBAND", 7) == 0)
2107 {
2108 int band = -1;
2109 char extra[32];
2110 tANI_U8 len = 0;
2111 hdd_getBand_helper(pHddCtx, &band);
2112
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002113 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002114 if (copy_to_user(priv_data.buf, &extra, len + 1))
2115 {
2116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2117 "%s: failed to copy data to user buffer", __func__);
2118 ret = -EFAULT;
2119 goto exit;
2120 }
2121 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002122 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2123 {
2124 tANI_U8 *value = command;
2125 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2126 tANI_U8 numChannels = 0;
2127 eHalStatus status = eHAL_STATUS_SUCCESS;
2128
2129 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2130 if (eHAL_STATUS_SUCCESS != status)
2131 {
2132 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2133 "%s: Failed to parse channel list information", __func__);
2134 ret = -EINVAL;
2135 goto exit;
2136 }
2137
2138 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2139 {
2140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2141 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2142 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2143 ret = -EINVAL;
2144 goto exit;
2145 }
2146 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2147 numChannels);
2148 if (eHAL_STATUS_SUCCESS != status)
2149 {
2150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2151 "%s: Failed to update channel list information", __func__);
2152 ret = -EINVAL;
2153 goto exit;
2154 }
2155 }
2156 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2157 {
2158 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2159 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002160 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002161 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002162 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002163
2164 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2165 ChannelList, &numChannels ))
2166 {
2167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2168 "%s: failed to get roam scan channel list", __func__);
2169 ret = -EFAULT;
2170 goto exit;
2171 }
2172 /* output channel list is of the format
2173 [Number of roam scan channels][Channel1][Channel2]... */
2174 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002175 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002176 for (j = 0; (j < numChannels); j++)
2177 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002178 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2179 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002180 }
2181
2182 if (copy_to_user(priv_data.buf, &extra, len + 1))
2183 {
2184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2185 "%s: failed to copy data to user buffer", __func__);
2186 ret = -EFAULT;
2187 goto exit;
2188 }
2189 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002190 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2191 {
2192 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2193 char extra[32];
2194 tANI_U8 len = 0;
2195
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002196 /* Check if the features OKC/CCX/11R are supported simultaneously,
2197 then this operation is not permitted (return FAILURE) */
2198 if (ccxMode &&
2199 hdd_is_okc_mode_enabled(pHddCtx) &&
2200 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2201 {
2202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2203 "%s: OKC/CCX/11R are supported simultaneously"
2204 " hence this operation is not permitted!", __func__);
2205 ret = -EPERM;
2206 goto exit;
2207 }
2208
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002209 len = scnprintf(extra, sizeof(extra), "%s %d",
2210 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002211 if (copy_to_user(priv_data.buf, &extra, len + 1))
2212 {
2213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2214 "%s: failed to copy data to user buffer", __func__);
2215 ret = -EFAULT;
2216 goto exit;
2217 }
2218 }
2219 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2220 {
2221 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2222 char extra[32];
2223 tANI_U8 len = 0;
2224
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002225 /* Check if the features OKC/CCX/11R are supported simultaneously,
2226 then this operation is not permitted (return FAILURE) */
2227 if (okcMode &&
2228 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2229 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2230 {
2231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2232 "%s: OKC/CCX/11R are supported simultaneously"
2233 " hence this operation is not permitted!", __func__);
2234 ret = -EPERM;
2235 goto exit;
2236 }
2237
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002238 len = scnprintf(extra, sizeof(extra), "%s %d",
2239 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002240 if (copy_to_user(priv_data.buf, &extra, len + 1))
2241 {
2242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2243 "%s: failed to copy data to user buffer", __func__);
2244 ret = -EFAULT;
2245 goto exit;
2246 }
2247 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002248 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002249 {
2250 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2251 char extra[32];
2252 tANI_U8 len = 0;
2253
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002254 len = scnprintf(extra, sizeof(extra), "%s %d",
2255 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002256 if (copy_to_user(priv_data.buf, &extra, len + 1))
2257 {
2258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2259 "%s: failed to copy data to user buffer", __func__);
2260 ret = -EFAULT;
2261 goto exit;
2262 }
2263 }
2264 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2265 {
2266 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2267 char extra[32];
2268 tANI_U8 len = 0;
2269
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002270 len = scnprintf(extra, sizeof(extra), "%s %d",
2271 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002272 if (copy_to_user(priv_data.buf, &extra, len + 1))
2273 {
2274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2275 "%s: failed to copy data to user buffer", __func__);
2276 ret = -EFAULT;
2277 goto exit;
2278 }
2279 }
2280 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2281 {
2282 tANI_U8 *value = command;
2283 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2284
2285 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2286 value = value + 26;
2287 /* Convert the value from ascii to integer */
2288 ret = kstrtou8(value, 10, &minTime);
2289 if (ret < 0)
2290 {
2291 /* If the input value is greater than max value of datatype, then also
2292 kstrtou8 fails */
2293 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2294 "%s: kstrtou8 failed range [%d - %d]", __func__,
2295 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2296 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2297 ret = -EINVAL;
2298 goto exit;
2299 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002300 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2301 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2302 {
2303 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2304 "scan min channel time value %d is out of range"
2305 " (Min: %d Max: %d)", minTime,
2306 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2307 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2308 ret = -EINVAL;
2309 goto exit;
2310 }
2311
2312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2313 "%s: Received Command to change channel min time = %d", __func__, minTime);
2314
2315 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2316 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2317 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002318 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2319 {
2320 tANI_U8 *value = command;
2321 tANI_U8 channel = 0;
2322 tANI_U8 dwellTime = 0;
2323 tANI_U8 bufLen = 0;
2324 tANI_U8 *buf = NULL;
2325 tSirMacAddr targetApBssid;
2326 eHalStatus status = eHAL_STATUS_SUCCESS;
2327 struct ieee80211_channel chan;
2328 tANI_U8 finalLen = 0;
2329 tANI_U8 *finalBuf = NULL;
2330 tANI_U8 temp = 0;
2331 u64 cookie;
2332 hdd_station_ctx_t *pHddStaCtx = NULL;
2333 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2334
2335 /* if not associated, no need to send action frame */
2336 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2337 {
2338 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2339 ret = -EINVAL;
2340 goto exit;
2341 }
2342
2343 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2344 &dwellTime, &buf, &bufLen);
2345 if (eHAL_STATUS_SUCCESS != status)
2346 {
2347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2348 "%s: Failed to parse send action frame data", __func__);
2349 ret = -EINVAL;
2350 goto exit;
2351 }
2352
2353 /* if the target bssid is different from currently associated AP,
2354 then no need to send action frame */
2355 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2356 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2357 {
2358 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2359 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002360 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002361 goto exit;
2362 }
2363
2364 /* if the channel number is different from operating channel then
2365 no need to send action frame */
2366 if (channel != pHddStaCtx->conn_info.operationChannel)
2367 {
2368 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2369 "%s: channel(%d) is different from operating channel(%d)",
2370 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2371 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002372 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002373 goto exit;
2374 }
2375 chan.center_freq = sme_ChnToFreq(channel);
2376
2377 finalLen = bufLen + 24;
2378 finalBuf = vos_mem_malloc(finalLen);
2379 if (NULL == finalBuf)
2380 {
2381 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2382 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002383 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002384 goto exit;
2385 }
2386 vos_mem_zero(finalBuf, finalLen);
2387
2388 /* Fill subtype */
2389 temp = SIR_MAC_MGMT_ACTION << 4;
2390 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2391
2392 /* Fill type */
2393 temp = SIR_MAC_MGMT_FRAME;
2394 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2395
2396 /* Fill destination address (bssid of the AP) */
2397 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2398
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002399 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002400 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2401
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002402 /* Fill BSSID (AP mac address) */
2403 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002404
2405 /* Fill received buffer from 24th address */
2406 vos_mem_copy(finalBuf + 24, buf, bufLen);
2407
Jeff Johnson11c33152013-04-16 17:52:40 -07002408 /* done with the parsed buffer */
2409 vos_mem_free(buf);
2410
Yue Maf49ba872013-08-19 12:04:25 -07002411 wlan_hdd_action( NULL,
2412#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2413 &(pAdapter->wdev),
2414#else
2415 dev,
2416#endif
2417 &chan, 0,
2418#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2419 NL80211_CHAN_HT20, 1,
2420#endif
2421 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002422 1, &cookie );
2423 vos_mem_free(finalBuf);
2424 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002425 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2426 {
2427 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2428 char extra[32];
2429 tANI_U8 len = 0;
2430
2431 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002432 len = scnprintf(extra, sizeof(extra), "%s %d",
2433 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002434 if (copy_to_user(priv_data.buf, &extra, len + 1))
2435 {
2436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2437 "%s: failed to copy data to user buffer", __func__);
2438 ret = -EFAULT;
2439 goto exit;
2440 }
2441 }
2442 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2443 {
2444 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002445 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002446
2447 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2448 value = value + 19;
2449 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002450 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002451 if (ret < 0)
2452 {
2453 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002454 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002456 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002457 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2458 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2459 ret = -EINVAL;
2460 goto exit;
2461 }
2462
2463 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2464 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2465 {
2466 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2467 "lfr mode value %d is out of range"
2468 " (Min: %d Max: %d)", maxTime,
2469 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2470 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2471 ret = -EINVAL;
2472 goto exit;
2473 }
2474
2475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2476 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2477
2478 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
2479 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2480 }
2481 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2482 {
2483 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2484 char extra[32];
2485 tANI_U8 len = 0;
2486
2487 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002488 len = scnprintf(extra, sizeof(extra), "%s %d",
2489 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002490 if (copy_to_user(priv_data.buf, &extra, len + 1))
2491 {
2492 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2493 "%s: failed to copy data to user buffer", __func__);
2494 ret = -EFAULT;
2495 goto exit;
2496 }
2497 }
2498 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2499 {
2500 tANI_U8 *value = command;
2501 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2502
2503 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2504 value = value + 16;
2505 /* Convert the value from ascii to integer */
2506 ret = kstrtou16(value, 10, &val);
2507 if (ret < 0)
2508 {
2509 /* If the input value is greater than max value of datatype, then also
2510 kstrtou16 fails */
2511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2512 "%s: kstrtou16 failed range [%d - %d]", __func__,
2513 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2514 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2515 ret = -EINVAL;
2516 goto exit;
2517 }
2518
2519 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2520 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2521 {
2522 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2523 "scan home time value %d is out of range"
2524 " (Min: %d Max: %d)", val,
2525 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2526 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2527 ret = -EINVAL;
2528 goto exit;
2529 }
2530
2531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2532 "%s: Received Command to change scan home time = %d", __func__, val);
2533
2534 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2535 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2536 }
2537 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2538 {
2539 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2540 char extra[32];
2541 tANI_U8 len = 0;
2542
2543 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002544 len = scnprintf(extra, sizeof(extra), "%s %d",
2545 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002546 if (copy_to_user(priv_data.buf, &extra, len + 1))
2547 {
2548 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2549 "%s: failed to copy data to user buffer", __func__);
2550 ret = -EFAULT;
2551 goto exit;
2552 }
2553 }
2554 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2555 {
2556 tANI_U8 *value = command;
2557 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2558
2559 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2560 value = value + 17;
2561 /* Convert the value from ascii to integer */
2562 ret = kstrtou8(value, 10, &val);
2563 if (ret < 0)
2564 {
2565 /* If the input value is greater than max value of datatype, then also
2566 kstrtou8 fails */
2567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2568 "%s: kstrtou8 failed range [%d - %d]", __func__,
2569 CFG_ROAM_INTRA_BAND_MIN,
2570 CFG_ROAM_INTRA_BAND_MAX);
2571 ret = -EINVAL;
2572 goto exit;
2573 }
2574
2575 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2576 (val > CFG_ROAM_INTRA_BAND_MAX))
2577 {
2578 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2579 "intra band mode value %d is out of range"
2580 " (Min: %d Max: %d)", val,
2581 CFG_ROAM_INTRA_BAND_MIN,
2582 CFG_ROAM_INTRA_BAND_MAX);
2583 ret = -EINVAL;
2584 goto exit;
2585 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2587 "%s: Received Command to change intra band = %d", __func__, val);
2588
2589 pHddCtx->cfg_ini->nRoamIntraBand = val;
2590 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2591 }
2592 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2593 {
2594 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2595 char extra[32];
2596 tANI_U8 len = 0;
2597
2598 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002599 len = scnprintf(extra, sizeof(extra), "%s %d",
2600 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002601 if (copy_to_user(priv_data.buf, &extra, len + 1))
2602 {
2603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2604 "%s: failed to copy data to user buffer", __func__);
2605 ret = -EFAULT;
2606 goto exit;
2607 }
2608 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002609 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2610 {
2611 tANI_U8 *value = command;
2612 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2613
2614 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2615 value = value + 15;
2616 /* Convert the value from ascii to integer */
2617 ret = kstrtou8(value, 10, &nProbes);
2618 if (ret < 0)
2619 {
2620 /* If the input value is greater than max value of datatype, then also
2621 kstrtou8 fails */
2622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2623 "%s: kstrtou8 failed range [%d - %d]", __func__,
2624 CFG_ROAM_SCAN_N_PROBES_MIN,
2625 CFG_ROAM_SCAN_N_PROBES_MAX);
2626 ret = -EINVAL;
2627 goto exit;
2628 }
2629
2630 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2631 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2632 {
2633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2634 "NProbes value %d is out of range"
2635 " (Min: %d Max: %d)", nProbes,
2636 CFG_ROAM_SCAN_N_PROBES_MIN,
2637 CFG_ROAM_SCAN_N_PROBES_MAX);
2638 ret = -EINVAL;
2639 goto exit;
2640 }
2641
2642 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2643 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2644
2645 pHddCtx->cfg_ini->nProbes = nProbes;
2646 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2647 }
2648 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2649 {
2650 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2651 char extra[32];
2652 tANI_U8 len = 0;
2653
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002654 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002655 if (copy_to_user(priv_data.buf, &extra, len + 1))
2656 {
2657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2658 "%s: failed to copy data to user buffer", __func__);
2659 ret = -EFAULT;
2660 goto exit;
2661 }
2662 }
2663 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2664 {
2665 tANI_U8 *value = command;
2666 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
2667
2668 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2669 /* input value is in units of msec */
2670 value = value + 20;
2671 /* Convert the value from ascii to integer */
2672 ret = kstrtou16(value, 10, &homeAwayTime);
2673 if (ret < 0)
2674 {
2675 /* If the input value is greater than max value of datatype, then also
2676 kstrtou8 fails */
2677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2678 "%s: kstrtou8 failed range [%d - %d]", __func__,
2679 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2680 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2681 ret = -EINVAL;
2682 goto exit;
2683 }
2684
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002685 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2686 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2687 {
2688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2689 "homeAwayTime value %d is out of range"
2690 " (Min: %d Max: %d)", homeAwayTime,
2691 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2692 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2693 ret = -EINVAL;
2694 goto exit;
2695 }
2696
2697 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2698 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002699 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2700 {
2701 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2702 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2703 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002704 }
2705 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2706 {
2707 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2708 char extra[32];
2709 tANI_U8 len = 0;
2710
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002711 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002712 if (copy_to_user(priv_data.buf, &extra, len + 1))
2713 {
2714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2715 "%s: failed to copy data to user buffer", __func__);
2716 ret = -EFAULT;
2717 goto exit;
2718 }
2719 }
2720 else if (strncmp(command, "REASSOC", 7) == 0)
2721 {
2722 tANI_U8 *value = command;
2723 tANI_U8 channel = 0;
2724 tSirMacAddr targetApBssid;
2725 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002726#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2727 tCsrHandoffRequest handoffInfo;
2728#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002729 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002730 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2731
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002732 /* if not associated, no need to proceed with reassoc */
2733 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2734 {
2735 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2736 ret = -EINVAL;
2737 goto exit;
2738 }
2739
2740 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2741 if (eHAL_STATUS_SUCCESS != status)
2742 {
2743 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2744 "%s: Failed to parse reassoc command data", __func__);
2745 ret = -EINVAL;
2746 goto exit;
2747 }
2748
2749 /* if the target bssid is same as currently associated AP,
2750 then no need to proceed with reassoc */
2751 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2752 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2753 {
2754 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2755 ret = -EINVAL;
2756 goto exit;
2757 }
2758
2759 /* Check channel number is a valid channel number */
2760 if(VOS_STATUS_SUCCESS !=
2761 wlan_hdd_validate_operation_channel(pAdapter, channel))
2762 {
2763 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002764 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002765 return -EINVAL;
2766 }
2767
2768 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002769#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2770 handoffInfo.channel = channel;
2771 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2772 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2773#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002774 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002775 else if (strncmp(command, "SETWESMODE", 10) == 0)
2776 {
2777 tANI_U8 *value = command;
2778 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2779
2780 /* Move pointer to ahead of SETWESMODE<delimiter> */
2781 value = value + 11;
2782 /* Convert the value from ascii to integer */
2783 ret = kstrtou8(value, 10, &wesMode);
2784 if (ret < 0)
2785 {
2786 /* If the input value is greater than max value of datatype, then also
2787 kstrtou8 fails */
2788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2789 "%s: kstrtou8 failed range [%d - %d]", __func__,
2790 CFG_ENABLE_WES_MODE_NAME_MIN,
2791 CFG_ENABLE_WES_MODE_NAME_MAX);
2792 ret = -EINVAL;
2793 goto exit;
2794 }
2795
2796 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2797 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2798 {
2799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2800 "WES Mode value %d is out of range"
2801 " (Min: %d Max: %d)", wesMode,
2802 CFG_ENABLE_WES_MODE_NAME_MIN,
2803 CFG_ENABLE_WES_MODE_NAME_MAX);
2804 ret = -EINVAL;
2805 goto exit;
2806 }
2807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2808 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2809
2810 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2811 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2812 }
2813 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2814 {
2815 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2816 char extra[32];
2817 tANI_U8 len = 0;
2818
Arif Hussain826d9412013-11-12 16:44:54 -08002819 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002820 if (copy_to_user(priv_data.buf, &extra, len + 1))
2821 {
2822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2823 "%s: failed to copy data to user buffer", __func__);
2824 ret = -EFAULT;
2825 goto exit;
2826 }
2827 }
2828#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002829#ifdef FEATURE_WLAN_LFR
2830 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2831 {
2832 tANI_U8 *value = command;
2833 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2834
2835 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2836 value = value + 12;
2837 /* Convert the value from ascii to integer */
2838 ret = kstrtou8(value, 10, &lfrMode);
2839 if (ret < 0)
2840 {
2841 /* If the input value is greater than max value of datatype, then also
2842 kstrtou8 fails */
2843 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2844 "%s: kstrtou8 failed range [%d - %d]", __func__,
2845 CFG_LFR_FEATURE_ENABLED_MIN,
2846 CFG_LFR_FEATURE_ENABLED_MAX);
2847 ret = -EINVAL;
2848 goto exit;
2849 }
2850
2851 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2852 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2853 {
2854 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2855 "lfr mode value %d is out of range"
2856 " (Min: %d Max: %d)", lfrMode,
2857 CFG_LFR_FEATURE_ENABLED_MIN,
2858 CFG_LFR_FEATURE_ENABLED_MAX);
2859 ret = -EINVAL;
2860 goto exit;
2861 }
2862
2863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2864 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2865
2866 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2867 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2868 }
2869#endif
2870#ifdef WLAN_FEATURE_VOWIFI_11R
2871 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2872 {
2873 tANI_U8 *value = command;
2874 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2875
2876 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2877 value = value + 18;
2878 /* Convert the value from ascii to integer */
2879 ret = kstrtou8(value, 10, &ft);
2880 if (ret < 0)
2881 {
2882 /* If the input value is greater than max value of datatype, then also
2883 kstrtou8 fails */
2884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2885 "%s: kstrtou8 failed range [%d - %d]", __func__,
2886 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2887 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2888 ret = -EINVAL;
2889 goto exit;
2890 }
2891
2892 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2893 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2894 {
2895 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2896 "ft mode value %d is out of range"
2897 " (Min: %d Max: %d)", ft,
2898 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2899 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2900 ret = -EINVAL;
2901 goto exit;
2902 }
2903
2904 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2905 "%s: Received Command to change ft mode = %d", __func__, ft);
2906
2907 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2908 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2909 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302910
2911 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2912 {
2913 tANI_U8 *value = command;
2914 tSirMacAddr targetApBssid;
2915 tANI_U8 trigger = 0;
2916 eHalStatus status = eHAL_STATUS_SUCCESS;
2917 hdd_station_ctx_t *pHddStaCtx = NULL;
2918 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2919
2920 /* if not associated, no need to proceed with reassoc */
2921 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2922 {
2923 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2924 ret = -EINVAL;
2925 goto exit;
2926 }
2927
2928 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2929 if (eHAL_STATUS_SUCCESS != status)
2930 {
2931 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2932 "%s: Failed to parse reassoc command data", __func__);
2933 ret = -EINVAL;
2934 goto exit;
2935 }
2936
2937 /* if the target bssid is same as currently associated AP,
2938 then no need to proceed with reassoc */
2939 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2940 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2941 {
2942 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2943 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2944 __func__);
2945 ret = -EINVAL;
2946 goto exit;
2947 }
2948
2949 /* Proceed with scan/roam */
2950 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2951 &targetApBssid[0],
2952 (tSmeFastRoamTrigger)(trigger));
2953 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002954#endif
2955#ifdef FEATURE_WLAN_CCX
2956 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2957 {
2958 tANI_U8 *value = command;
2959 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2960
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002961 /* Check if the features OKC/CCX/11R are supported simultaneously,
2962 then this operation is not permitted (return FAILURE) */
2963 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2964 hdd_is_okc_mode_enabled(pHddCtx) &&
2965 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2966 {
2967 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2968 "%s: OKC/CCX/11R are supported simultaneously"
2969 " hence this operation is not permitted!", __func__);
2970 ret = -EPERM;
2971 goto exit;
2972 }
2973
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002974 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2975 value = value + 11;
2976 /* Convert the value from ascii to integer */
2977 ret = kstrtou8(value, 10, &ccxMode);
2978 if (ret < 0)
2979 {
2980 /* If the input value is greater than max value of datatype, then also
2981 kstrtou8 fails */
2982 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2983 "%s: kstrtou8 failed range [%d - %d]", __func__,
2984 CFG_CCX_FEATURE_ENABLED_MIN,
2985 CFG_CCX_FEATURE_ENABLED_MAX);
2986 ret = -EINVAL;
2987 goto exit;
2988 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002989 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2990 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2991 {
2992 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2993 "Ccx mode value %d is out of range"
2994 " (Min: %d Max: %d)", ccxMode,
2995 CFG_CCX_FEATURE_ENABLED_MIN,
2996 CFG_CCX_FEATURE_ENABLED_MAX);
2997 ret = -EINVAL;
2998 goto exit;
2999 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003000 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3001 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3002
3003 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3004 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3005 }
3006#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003007 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3008 {
3009 tANI_U8 *value = command;
3010 tANI_BOOLEAN roamScanControl = 0;
3011
3012 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3013 value = value + 19;
3014 /* Convert the value from ascii to integer */
3015 ret = kstrtou8(value, 10, &roamScanControl);
3016 if (ret < 0)
3017 {
3018 /* If the input value is greater than max value of datatype, then also
3019 kstrtou8 fails */
3020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3021 "%s: kstrtou8 failed ", __func__);
3022 ret = -EINVAL;
3023 goto exit;
3024 }
3025
3026 if (0 != roamScanControl)
3027 {
3028 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3029 "roam scan control invalid value = %d",
3030 roamScanControl);
3031 ret = -EINVAL;
3032 goto exit;
3033 }
3034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3035 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3036
3037 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3038 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003039#ifdef FEATURE_WLAN_OKC
3040 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3041 {
3042 tANI_U8 *value = command;
3043 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3044
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003045 /* Check if the features OKC/CCX/11R are supported simultaneously,
3046 then this operation is not permitted (return FAILURE) */
3047 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3048 hdd_is_okc_mode_enabled(pHddCtx) &&
3049 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3050 {
3051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3052 "%s: OKC/CCX/11R are supported simultaneously"
3053 " hence this operation is not permitted!", __func__);
3054 ret = -EPERM;
3055 goto exit;
3056 }
3057
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003058 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3059 value = value + 11;
3060 /* Convert the value from ascii to integer */
3061 ret = kstrtou8(value, 10, &okcMode);
3062 if (ret < 0)
3063 {
3064 /* If the input value is greater than max value of datatype, then also
3065 kstrtou8 fails */
3066 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3067 "%s: kstrtou8 failed range [%d - %d]", __func__,
3068 CFG_OKC_FEATURE_ENABLED_MIN,
3069 CFG_OKC_FEATURE_ENABLED_MAX);
3070 ret = -EINVAL;
3071 goto exit;
3072 }
3073
3074 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3075 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3076 {
3077 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3078 "Okc mode value %d is out of range"
3079 " (Min: %d Max: %d)", okcMode,
3080 CFG_OKC_FEATURE_ENABLED_MIN,
3081 CFG_OKC_FEATURE_ENABLED_MAX);
3082 ret = -EINVAL;
3083 goto exit;
3084 }
3085
3086 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3087 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3088
3089 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3090 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003091#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003092 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3093 {
3094 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3095 char extra[32];
3096 tANI_U8 len = 0;
3097
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003098 len = scnprintf(extra, sizeof(extra), "%s %d",
3099 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003100 if (copy_to_user(priv_data.buf, &extra, len + 1))
3101 {
3102 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3103 "%s: failed to copy data to user buffer", __func__);
3104 ret = -EFAULT;
3105 goto exit;
3106 }
3107 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303108#ifdef WLAN_FEATURE_PACKET_FILTERING
3109 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3110 {
3111 tANI_U8 filterType = 0;
3112 tANI_U8 *value = command;
3113
3114 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3115 value = value + 22;
3116
3117 /* Convert the value from ascii to integer */
3118 ret = kstrtou8(value, 10, &filterType);
3119 if (ret < 0)
3120 {
3121 /* If the input value is greater than max value of datatype,
3122 * then also kstrtou8 fails
3123 */
3124 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3125 "%s: kstrtou8 failed range ", __func__);
3126 ret = -EINVAL;
3127 goto exit;
3128 }
3129
3130 if (filterType != 0 && filterType != 1)
3131 {
3132 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3133 "%s: Accepted Values are 0 and 1 ", __func__);
3134 ret = -EINVAL;
3135 goto exit;
3136 }
3137 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3138 pAdapter->sessionId);
3139 }
3140#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303141 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3142 {
3143 char *dhcpPhase;
3144 dhcpPhase = command + 12;
3145 if ('1' == *dhcpPhase)
3146 {
3147 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3148 pAdapter->macAddressCurrent.bytes);
3149 }
3150 else if ('2' == *dhcpPhase)
3151 {
3152 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3153 pAdapter->macAddressCurrent.bytes);
3154 }
3155 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003156 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3157 {
3158 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3159 }
3160 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3161 {
3162 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3163 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303164 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3165 {
3166 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3167 char extra[32];
3168 tANI_U8 len = 0;
3169
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003170 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303171 (int)pCfg->nActiveMaxChnTime);
3172 if (copy_to_user(priv_data.buf, &extra, len + 1))
3173 {
3174 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3175 "%s: failed to copy data to user buffer", __func__);
3176 ret = -EFAULT;
3177 goto exit;
3178 }
3179 ret = len;
3180 }
3181 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3182 {
3183 tANI_U8 *value = command;
3184 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3185 int val = 0, temp;
3186
3187 value = value + 13;
3188 temp = kstrtou32(value, 10, &val);
3189 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3190 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3191 {
3192 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3193 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3194 ret = -EFAULT;
3195 goto exit;
3196 }
3197 pCfg->nActiveMaxChnTime = val;
3198 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003199 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3200 {
3201 tANI_U8 filterType = 0;
3202 tANI_U8 *value;
3203 value = command + 9;
3204
3205 /* Convert the value from ascii to integer */
3206 ret = kstrtou8(value, 10, &filterType);
3207 if (ret < 0)
3208 {
3209 /* If the input value is greater than max value of datatype,
3210 * then also kstrtou8 fails
3211 */
3212 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3213 "%s: kstrtou8 failed range ", __func__);
3214 ret = -EINVAL;
3215 goto exit;
3216 }
3217 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3218 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3219 {
3220 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3221 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3222 " 2-Sink ", __func__);
3223 ret = -EINVAL;
3224 goto exit;
3225 }
3226 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3227 pHddCtx->drvr_miracast = filterType;
3228 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3229 }
Leo Chang614d2072013-08-22 14:59:44 -07003230 else if (strncmp(command, "SETMCRATE", 9) == 0)
3231 {
Leo Chang614d2072013-08-22 14:59:44 -07003232 tANI_U8 *value = command;
3233 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003234 tSirRateUpdateInd *rateUpdate;
3235 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003236
3237 /* Only valid for SAP mode */
3238 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3239 {
3240 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3241 "%s: SAP mode is not running", __func__);
3242 ret = -EFAULT;
3243 goto exit;
3244 }
3245
3246 /* Move pointer to ahead of SETMCRATE<delimiter> */
3247 /* input value is in units of hundred kbps */
3248 value = value + 10;
3249 /* Convert the value from ascii to integer, decimal base */
3250 ret = kstrtouint(value, 10, &targetRate);
3251
Leo Chang1f98cbd2013-10-17 15:03:52 -07003252 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3253 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003254 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003255 hddLog(VOS_TRACE_LEVEL_ERROR,
3256 "%s: SETMCRATE indication alloc fail", __func__);
3257 ret = -EFAULT;
3258 goto exit;
3259 }
3260 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3261
3262 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3263 "MC Target rate %d", targetRate);
3264 /* Ignore unicast */
3265 rateUpdate->ucastDataRate = -1;
3266 rateUpdate->mcastDataRate24GHz = targetRate;
3267 rateUpdate->mcastDataRate5GHz = targetRate;
3268 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3269 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3270 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3271 if (eHAL_STATUS_SUCCESS != status)
3272 {
3273 hddLog(VOS_TRACE_LEVEL_ERROR,
3274 "%s: SET_MC_RATE failed", __func__);
3275 vos_mem_free(rateUpdate);
3276 ret = -EFAULT;
3277 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003278 }
3279 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303280#ifdef FEATURE_WLAN_BATCH_SCAN
3281 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3282 {
3283 char extra[32];
3284 tANI_U8 len = 0;
3285 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3286
3287 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3288 {
3289 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3290 "%s: Batch scan feature is not supported by FW", __func__);
3291 ret = -EINVAL;
3292 goto exit;
3293 }
3294
3295 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3296 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3297 {
3298 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3299 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3300 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3301 " mode",
3302 pAdapter->device_mode);
3303 ret = -EINVAL;
3304 goto exit;
3305 }
3306
Arif Hussain826d9412013-11-12 16:44:54 -08003307 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
Rajeev79dbe4c2013-10-05 11:03:42 +05303308 version);
3309 if (copy_to_user(priv_data.buf, &extra, len + 1))
3310 {
3311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3312 "%s: failed to copy data to user buffer", __func__);
3313 ret = -EFAULT;
3314 goto exit;
3315 }
3316 ret = HDD_BATCH_SCAN_VERSION;
3317 }
3318 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3319 {
3320 int status;
3321 tANI_U8 *value = (command + 16);
3322 eHalStatus halStatus;
3323 unsigned long rc;
3324 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3325 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3326
3327 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3328 {
3329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3330 "%s: Batch scan feature is not supported by FW", __func__);
3331 ret = -EINVAL;
3332 goto exit;
3333 }
3334
Rajeev Kumar20140c12013-10-21 19:39:02 -07003335
Rajeev79dbe4c2013-10-05 11:03:42 +05303336 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
Rajeev Kumar5286bb92013-12-05 11:52:10 -08003337 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
3338 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
Rajeev79dbe4c2013-10-05 11:03:42 +05303339 {
3340 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003341 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303342 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3343 pAdapter->device_mode);
3344 ret = -EINVAL;
3345 goto exit;
3346 }
3347
Rajeev Kumar20140c12013-10-21 19:39:02 -07003348
Rajeev79dbe4c2013-10-05 11:03:42 +05303349 status = hdd_parse_set_batchscan_command(value, pReq);
3350 if (status)
3351 {
3352 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003353 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303354 ret = -EINVAL;
3355 goto exit;
3356 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003357
3358
Rajeev79dbe4c2013-10-05 11:03:42 +05303359 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3360 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3361 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3362 pAdapter);
3363
3364 if ( eHAL_STATUS_SUCCESS == halStatus )
3365 {
3366 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3367 "sme_SetBatchScanReq returned success halStatus %d",
3368 halStatus);
3369 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3370 {
3371 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3372 rc = wait_for_completion_timeout(
3373 &pAdapter->hdd_set_batch_scan_req_var,
3374 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3375 if (0 == rc)
3376 {
3377 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3378 "%s: Timeout waiting for set batch scan to complete",
3379 __func__);
3380 ret = -EINVAL;
3381 goto exit;
3382 }
3383 }
3384 if ( !pRsp->nScansToBatch )
3385 {
3386 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3387 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003388 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303389 ret = -EINVAL;
3390 goto exit;
3391 }
3392 /*As per the Batch Scan Framework API we should return the MIN of
3393 either MSCAN or the max # of scans firmware can cache*/
3394 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3395
Rajeev Kumar20140c12013-10-21 19:39:02 -07003396 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3397
Rajeev79dbe4c2013-10-05 11:03:42 +05303398 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3399 "%s: request MSCAN %d response MSCAN %d ret %d",
3400 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3401 }
3402 else
3403 {
3404 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3405 "sme_SetBatchScanReq returned failure halStatus %d",
3406 halStatus);
3407 ret = -EINVAL;
3408 goto exit;
3409 }
3410 }
3411 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3412 {
3413 eHalStatus halStatus;
3414 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3415 pInd->param = 0;
3416
3417 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3418 {
3419 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3420 "%s: Batch scan feature is not supported by FW", __func__);
3421 ret = -EINVAL;
3422 goto exit;
3423 }
3424
Rajeev Kumar20140c12013-10-21 19:39:02 -07003425 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303426 {
3427 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003428 "Batch scan is not yet enabled batch scan state %d",
3429 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303430 ret = -EINVAL;
3431 goto exit;
3432 }
3433
Rajeev Kumar20140c12013-10-21 19:39:02 -07003434 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3435
Rajeev79dbe4c2013-10-05 11:03:42 +05303436 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3437 pAdapter->sessionId);
3438 if ( eHAL_STATUS_SUCCESS == halStatus )
3439 {
3440 ret = 0;
3441 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3442 "sme_StopBatchScanInd returned success halStatus %d",
3443 halStatus);
3444 }
3445 else
3446 {
3447 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3448 "sme_StopBatchScanInd returned failure halStatus %d",
3449 halStatus);
3450 ret = -EINVAL;
3451 goto exit;
3452 }
3453 }
3454 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3455 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003456 tANI_U32 remain_len;
3457
Rajeev79dbe4c2013-10-05 11:03:42 +05303458 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3459 {
3460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3461 "%s: Batch scan feature is not supported by FW", __func__);
3462 ret = -EINVAL;
3463 goto exit;
3464 }
3465
Rajeev Kumar20140c12013-10-21 19:39:02 -07003466 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303467 {
3468 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003469 "Batch scan is not yet enabled could not return results"
3470 "Batch Scan state %d",
3471 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303472 ret = -EINVAL;
3473 goto exit;
3474 }
3475
3476 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003477 remain_len = priv_data.total_len - priv_data.used_len;
3478 if (remain_len < priv_data.total_len)
3479 {
3480 /*Clear previous batch scan response data if any*/
3481 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3482 }
3483 else
3484 {
3485 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3486 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003487 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003488 priv_data.total_len, priv_data.used_len, remain_len);
3489 ret = -EINVAL;
3490 goto exit;
3491 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303492 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3493 }
3494#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003495#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3496 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3497 {
3498 tANI_U8 *value = command;
3499 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3500 tANI_U8 numChannels = 0;
3501 eHalStatus status = eHAL_STATUS_SUCCESS;
3502
3503 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3504 if (eHAL_STATUS_SUCCESS != status)
3505 {
3506 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3507 "%s: Failed to parse channel list information", __func__);
3508 ret = -EINVAL;
3509 goto exit;
3510 }
3511
3512 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3513 {
3514 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3515 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3516 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3517 ret = -EINVAL;
3518 goto exit;
3519 }
3520 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3521 ChannelList,
3522 numChannels);
3523 if (eHAL_STATUS_SUCCESS != status)
3524 {
3525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3526 "%s: Failed to update channel list information", __func__);
3527 ret = -EINVAL;
3528 goto exit;
3529 }
3530 }
3531 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3532 {
3533 tANI_U8 *value = command;
3534 char extra[128] = {0};
3535 int len = 0;
3536 tANI_U8 tid = 0;
3537 hdd_station_ctx_t *pHddStaCtx = NULL;
3538 tAniTrafStrmMetrics tsmMetrics;
3539 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3540
3541 /* if not associated, return error */
3542 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3543 {
3544 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3545 ret = -EINVAL;
3546 goto exit;
3547 }
3548
3549 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3550 value = value + 12;
3551 /* Convert the value from ascii to integer */
3552 ret = kstrtou8(value, 10, &tid);
3553 if (ret < 0)
3554 {
3555 /* If the input value is greater than max value of datatype, then also
3556 kstrtou8 fails */
3557 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3558 "%s: kstrtou8 failed range [%d - %d]", __func__,
3559 TID_MIN_VALUE,
3560 TID_MAX_VALUE);
3561 ret = -EINVAL;
3562 goto exit;
3563 }
3564
3565 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3566 {
3567 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3568 "tid value %d is out of range"
3569 " (Min: %d Max: %d)", tid,
3570 TID_MIN_VALUE,
3571 TID_MAX_VALUE);
3572 ret = -EINVAL;
3573 goto exit;
3574 }
3575
3576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3577 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3578
3579 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3580 {
3581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3582 "%s: failed to get tsm stats", __func__);
3583 ret = -EFAULT;
3584 goto exit;
3585 }
3586
3587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3588 "UplinkPktQueueDly(%d)\n"
3589 "UplinkPktQueueDlyHist[0](%d)\n"
3590 "UplinkPktQueueDlyHist[1](%d)\n"
3591 "UplinkPktQueueDlyHist[2](%d)\n"
3592 "UplinkPktQueueDlyHist[3](%d)\n"
3593 "UplinkPktTxDly(%lu)\n"
3594 "UplinkPktLoss(%d)\n"
3595 "UplinkPktCount(%d)\n"
3596 "RoamingCount(%d)\n"
3597 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3598 tsmMetrics.UplinkPktQueueDlyHist[0],
3599 tsmMetrics.UplinkPktQueueDlyHist[1],
3600 tsmMetrics.UplinkPktQueueDlyHist[2],
3601 tsmMetrics.UplinkPktQueueDlyHist[3],
3602 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3603 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3604
3605 /* Output TSM stats is of the format
3606 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3607 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003608 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003609 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3610 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3611 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3612 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3613 tsmMetrics.RoamingDly);
3614
3615 if (copy_to_user(priv_data.buf, &extra, len + 1))
3616 {
3617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3618 "%s: failed to copy data to user buffer", __func__);
3619 ret = -EFAULT;
3620 goto exit;
3621 }
3622 }
3623 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3624 {
3625 tANI_U8 *value = command;
3626 tANI_U8 *cckmIe = NULL;
3627 tANI_U8 cckmIeLen = 0;
3628 eHalStatus status = eHAL_STATUS_SUCCESS;
3629
3630 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3631 if (eHAL_STATUS_SUCCESS != status)
3632 {
3633 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3634 "%s: Failed to parse cckm ie data", __func__);
3635 ret = -EINVAL;
3636 goto exit;
3637 }
3638
3639 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3640 {
3641 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3642 "%s: CCKM Ie input length is more than max[%d]", __func__,
3643 DOT11F_IE_RSN_MAX_LEN);
3644 if (NULL != cckmIe)
3645 {
3646 vos_mem_free(cckmIe);
3647 }
3648 ret = -EINVAL;
3649 goto exit;
3650 }
3651 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3652 if (NULL != cckmIe)
3653 {
3654 vos_mem_free(cckmIe);
3655 }
3656 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003657 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3658 {
3659 tANI_U8 *value = command;
3660 tCsrCcxBeaconReq ccxBcnReq;
3661 eHalStatus status = eHAL_STATUS_SUCCESS;
3662 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3663 if (eHAL_STATUS_SUCCESS != status)
3664 {
3665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3666 "%s: Failed to parse ccx beacon req", __func__);
3667 ret = -EINVAL;
3668 goto exit;
3669 }
3670
3671 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3672 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003673#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003674 else {
3675 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3676 __func__, command);
3677 }
3678
Jeff Johnson295189b2012-06-20 16:38:30 -07003679 }
3680exit:
3681 if (command)
3682 {
3683 kfree(command);
3684 }
3685 return ret;
3686}
3687
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003688
3689
3690#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003691/**---------------------------------------------------------------------------
3692
3693 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3694
3695 This function parses the ccx beacon request passed in the format
3696 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3697 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3698 <space>Scan Mode N<space>Meas Duration N
3699 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3700 then take N.
3701 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3702 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3703 This function does not take care of removing duplicate channels from the list
3704
3705 \param - pValue Pointer to data
3706 \param - pCcxBcnReq output pointer to store parsed ie information
3707
3708 \return - 0 for success non-zero for failure
3709
3710 --------------------------------------------------------------------------*/
3711static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3712 tCsrCcxBeaconReq *pCcxBcnReq)
3713{
3714 tANI_U8 *inPtr = pValue;
3715 int tempInt = 0;
3716 int j = 0, i = 0, v = 0;
3717 char buf[32];
3718
3719 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3720 /*no argument after the command*/
3721 if (NULL == inPtr)
3722 {
3723 return -EINVAL;
3724 }
3725 /*no space after the command*/
3726 else if (SPACE_ASCII_VALUE != *inPtr)
3727 {
3728 return -EINVAL;
3729 }
3730
3731 /*removing empty spaces*/
3732 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3733
3734 /*no argument followed by spaces*/
3735 if ('\0' == *inPtr) return -EINVAL;
3736
3737 /*getting the first argument ie measurement token*/
3738 v = sscanf(inPtr, "%32s ", buf);
3739 if (1 != v) return -EINVAL;
3740
3741 v = kstrtos32(buf, 10, &tempInt);
3742 if ( v < 0) return -EINVAL;
3743
3744 pCcxBcnReq->numBcnReqIe = tempInt;
3745
3746 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3747 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3748
3749 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3750 {
3751 for (i = 0; i < 4; i++)
3752 {
3753 /*inPtr pointing to the beginning of first space after number of ie fields*/
3754 inPtr = strpbrk( inPtr, " " );
3755 /*no ie data after the number of ie fields argument*/
3756 if (NULL == inPtr) return -EINVAL;
3757
3758 /*removing empty space*/
3759 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3760
3761 /*no ie data after the number of ie fields argument and spaces*/
3762 if ( '\0' == *inPtr ) return -EINVAL;
3763
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 switch (i)
3771 {
3772 case 0: /* Measurement token */
3773 if (tempInt <= 0)
3774 {
3775 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3776 "Invalid Measurement Token(%d)", tempInt);
3777 return -EINVAL;
3778 }
3779 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3780 break;
3781
3782 case 1: /* Channel number */
3783 if ((tempInt <= 0) ||
3784 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3785 {
3786 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3787 "Invalid Channel Number(%d)", tempInt);
3788 return -EINVAL;
3789 }
3790 pCcxBcnReq->bcnReq[j].channel = tempInt;
3791 break;
3792
3793 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003794 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003795 {
3796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3797 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3798 return -EINVAL;
3799 }
3800 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3801 break;
3802
3803 case 3: /* Measurement duration */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003804 if (((tempInt <= 0) && (pCcxBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
3805 ((tempInt < 0) && (pCcxBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003806 {
3807 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3808 "Invalid Measurement Duration(%d)", tempInt);
3809 return -EINVAL;
3810 }
3811 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3812 break;
3813 }
3814 }
3815 }
3816
3817 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3818 {
3819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3820 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3821 j,
3822 pCcxBcnReq->bcnReq[j].measurementToken,
3823 pCcxBcnReq->bcnReq[j].channel,
3824 pCcxBcnReq->bcnReq[j].scanMode,
3825 pCcxBcnReq->bcnReq[j].measurementDuration);
3826 }
3827
3828 return VOS_STATUS_SUCCESS;
3829}
3830
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003831static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3832{
3833 struct statsContext *pStatsContext = NULL;
3834 hdd_adapter_t *pAdapter = NULL;
3835
3836 if (NULL == pContext)
3837 {
3838 hddLog(VOS_TRACE_LEVEL_ERROR,
3839 "%s: Bad param, pContext [%p]",
3840 __func__, pContext);
3841 return;
3842 }
3843
3844 /* there is a race condition that exists between this callback function
3845 and the caller since the caller could time out either before or
3846 while this code is executing. we'll assume the timeout hasn't
3847 occurred, but we'll verify that right before we save our work */
3848
3849 pStatsContext = pContext;
3850 pAdapter = pStatsContext->pAdapter;
3851 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3852 {
3853 /* the caller presumably timed out so there is nothing we can do */
3854 hddLog(VOS_TRACE_LEVEL_WARN,
3855 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3856 __func__, pAdapter, pStatsContext->magic);
3857 return;
3858 }
3859
3860 /* the race is on. caller could have timed out immediately after
3861 we verified the magic, but if so, caller will wait a short time
3862 for us to copy over the tsm stats */
3863 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3864 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3865 tsmMetrics.UplinkPktQueueDlyHist,
3866 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3867 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3868 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3869 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3870 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3871 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3872 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3873
3874 /* and notify the caller */
3875 complete(&pStatsContext->completion);
3876}
3877
3878
3879
3880static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3881 tAniTrafStrmMetrics* pTsmMetrics)
3882{
3883 hdd_station_ctx_t *pHddStaCtx = NULL;
3884 eHalStatus hstatus;
3885 long lrc;
3886 struct statsContext context;
3887 hdd_context_t *pHddCtx = NULL;
3888
3889 if (NULL == pAdapter)
3890 {
3891 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3892 return VOS_STATUS_E_FAULT;
3893 }
3894
3895 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3896 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3897
3898 /* we are connected prepare our callback context */
3899 init_completion(&context.completion);
3900 context.pAdapter = pAdapter;
3901 context.magic = STATS_CONTEXT_MAGIC;
3902
3903 /* query tsm stats */
3904 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3905 pHddStaCtx->conn_info.staId[ 0 ],
3906 pHddStaCtx->conn_info.bssId,
3907 &context, pHddCtx->pvosContext, tid);
3908
3909 if (eHAL_STATUS_SUCCESS != hstatus)
3910 {
3911 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3912 return hstatus;
3913 }
3914 else
3915 {
3916 /* request was sent -- wait for the response */
3917 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3918 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3919 /* either we have a response or we timed out
3920 either way, first invalidate our magic */
3921 context.magic = 0;
3922 if (lrc <= 0)
3923 {
3924 hddLog(VOS_TRACE_LEVEL_ERROR,
3925 "%s: SME %s while retrieving statistics",
3926 __func__, (0 == lrc) ? "timeout" : "interrupt");
3927 /* there is a race condition such that the callback
3928 function could be executing at the same time we are. of
3929 primary concern is if the callback function had already
3930 verified the "magic" but hasn't yet set the completion
3931 variable. Since the completion variable is on our
3932 stack, we'll delay just a bit to make sure the data is
3933 still valid if that is the case */
3934 msleep(50);
3935 return (VOS_STATUS_E_TIMEOUT);
3936 }
3937 }
3938 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3939 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3940 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3941 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3942 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3943 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3944 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3945 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3946 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3947 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3948
3949 return VOS_STATUS_SUCCESS;
3950}
3951#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3952
Srinivas Girigowdade697412013-02-14 16:31:48 -08003953#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3954void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3955{
3956 eCsrBand band = -1;
3957 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3958 switch (band)
3959 {
3960 case eCSR_BAND_ALL:
3961 *pBand = WLAN_HDD_UI_BAND_AUTO;
3962 break;
3963
3964 case eCSR_BAND_24:
3965 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3966 break;
3967
3968 case eCSR_BAND_5G:
3969 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3970 break;
3971
3972 default:
3973 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3974 *pBand = -1;
3975 break;
3976 }
3977}
3978
3979/**---------------------------------------------------------------------------
3980
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003981 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3982
3983 This function parses the send action frame data passed in the format
3984 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3985
Srinivas Girigowda56076852013-08-20 14:00:50 -07003986 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003987 \param - pTargetApBssid Pointer to target Ap bssid
3988 \param - pChannel Pointer to the Target AP channel
3989 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3990 \param - pBuf Pointer to data
3991 \param - pBufLen Pointer to data length
3992
3993 \return - 0 for success non-zero for failure
3994
3995 --------------------------------------------------------------------------*/
3996VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3997 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3998{
3999 tANI_U8 *inPtr = pValue;
4000 tANI_U8 *dataEnd;
4001 int tempInt;
4002 int j = 0;
4003 int i = 0;
4004 int v = 0;
4005 tANI_U8 tempBuf[32];
4006 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004007 /* 12 hexa decimal digits and 5 ':' */
4008 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004009
4010 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4011 /*no argument after the command*/
4012 if (NULL == inPtr)
4013 {
4014 return -EINVAL;
4015 }
4016
4017 /*no space after the command*/
4018 else if (SPACE_ASCII_VALUE != *inPtr)
4019 {
4020 return -EINVAL;
4021 }
4022
4023 /*removing empty spaces*/
4024 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4025
4026 /*no argument followed by spaces*/
4027 if ('\0' == *inPtr)
4028 {
4029 return -EINVAL;
4030 }
4031
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004032 v = sscanf(inPtr, "%17s", macAddress);
4033 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004034 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004035 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4036 "Invalid MAC address or All hex inputs are not read (%d)", v);
4037 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004038 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004039
4040 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4041 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4042 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4043 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4044 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4045 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004046
4047 /* point to the next argument */
4048 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4049 /*no argument after the command*/
4050 if (NULL == inPtr) return -EINVAL;
4051
4052 /*removing empty spaces*/
4053 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4054
4055 /*no argument followed by spaces*/
4056 if ('\0' == *inPtr)
4057 {
4058 return -EINVAL;
4059 }
4060
4061 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004062 v = sscanf(inPtr, "%32s ", tempBuf);
4063 if (1 != v) return -EINVAL;
4064
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004065 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304066 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4067 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004068
4069 *pChannel = tempInt;
4070
4071 /* point to the next argument */
4072 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4073 /*no argument after the command*/
4074 if (NULL == inPtr) return -EINVAL;
4075 /*removing empty spaces*/
4076 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4077
4078 /*no argument followed by spaces*/
4079 if ('\0' == *inPtr)
4080 {
4081 return -EINVAL;
4082 }
4083
4084 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004085 v = sscanf(inPtr, "%32s ", tempBuf);
4086 if (1 != v) return -EINVAL;
4087
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004088 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304089 if ( v < 0 || tempInt <= 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004090
4091 *pDwellTime = tempInt;
4092
4093 /* point to the next argument */
4094 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4095 /*no argument after the command*/
4096 if (NULL == inPtr) return -EINVAL;
4097 /*removing empty spaces*/
4098 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4099
4100 /*no argument followed by spaces*/
4101 if ('\0' == *inPtr)
4102 {
4103 return -EINVAL;
4104 }
4105
4106 /* find the length of data */
4107 dataEnd = inPtr;
4108 while(('\0' != *dataEnd) )
4109 {
4110 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004111 }
Kiet Lambe150c22013-11-21 16:30:32 +05304112 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004113 if ( *pBufLen <= 0) return -EINVAL;
4114
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004115 /* Allocate the number of bytes based on the number of input characters
4116 whether it is even or odd.
4117 if the number of input characters are even, then we need N/2 byte.
4118 if the number of input characters are odd, then we need do (N+1)/2 to
4119 compensate rounding off.
4120 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4121 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4122 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004123 if (NULL == *pBuf)
4124 {
4125 hddLog(VOS_TRACE_LEVEL_FATAL,
4126 "%s: vos_mem_alloc failed ", __func__);
4127 return -EINVAL;
4128 }
4129
4130 /* the buffer received from the upper layer is character buffer,
4131 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4132 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4133 and f0 in 3rd location */
4134 for (i = 0, j = 0; j < *pBufLen; j += 2)
4135 {
Kiet Lambe150c22013-11-21 16:30:32 +05304136 if( j+1 == *pBufLen)
4137 {
4138 tempByte = hdd_parse_hex(inPtr[j]);
4139 }
4140 else
4141 {
4142 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4143 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004144 (*pBuf)[i++] = tempByte;
4145 }
4146 *pBufLen = i;
4147 return VOS_STATUS_SUCCESS;
4148}
4149
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004150/**---------------------------------------------------------------------------
4151
Srinivas Girigowdade697412013-02-14 16:31:48 -08004152 \brief hdd_parse_channellist() - HDD Parse channel list
4153
4154 This function parses the channel list passed in the format
4155 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004156 if the Number of channels (N) does not match with the actual number of channels passed
4157 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4158 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4159 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4160 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004161
4162 \param - pValue Pointer to input channel list
4163 \param - ChannelList Pointer to local output array to record channel list
4164 \param - pNumChannels Pointer to number of roam scan channels
4165
4166 \return - 0 for success non-zero for failure
4167
4168 --------------------------------------------------------------------------*/
4169VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4170{
4171 tANI_U8 *inPtr = pValue;
4172 int tempInt;
4173 int j = 0;
4174 int v = 0;
4175 char buf[32];
4176
4177 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4178 /*no argument after the command*/
4179 if (NULL == inPtr)
4180 {
4181 return -EINVAL;
4182 }
4183
4184 /*no space after the command*/
4185 else if (SPACE_ASCII_VALUE != *inPtr)
4186 {
4187 return -EINVAL;
4188 }
4189
4190 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004191 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004192
4193 /*no argument followed by spaces*/
4194 if ('\0' == *inPtr)
4195 {
4196 return -EINVAL;
4197 }
4198
4199 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004200 v = sscanf(inPtr, "%32s ", buf);
4201 if (1 != v) return -EINVAL;
4202
Srinivas Girigowdade697412013-02-14 16:31:48 -08004203 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004204 if ((v < 0) ||
4205 (tempInt <= 0) ||
4206 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4207 {
4208 return -EINVAL;
4209 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004210
4211 *pNumChannels = tempInt;
4212
4213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4214 "Number of channels are: %d", *pNumChannels);
4215
4216 for (j = 0; j < (*pNumChannels); j++)
4217 {
4218 /*inPtr pointing to the beginning of first space after number of channels*/
4219 inPtr = strpbrk( inPtr, " " );
4220 /*no channel list after the number of channels argument*/
4221 if (NULL == inPtr)
4222 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004223 if (0 != j)
4224 {
4225 *pNumChannels = j;
4226 return VOS_STATUS_SUCCESS;
4227 }
4228 else
4229 {
4230 return -EINVAL;
4231 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004232 }
4233
4234 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004235 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004236
4237 /*no channel list after the number of channels argument and spaces*/
4238 if ( '\0' == *inPtr )
4239 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004240 if (0 != j)
4241 {
4242 *pNumChannels = j;
4243 return VOS_STATUS_SUCCESS;
4244 }
4245 else
4246 {
4247 return -EINVAL;
4248 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004249 }
4250
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004251 v = sscanf(inPtr, "%32s ", buf);
4252 if (1 != v) return -EINVAL;
4253
Srinivas Girigowdade697412013-02-14 16:31:48 -08004254 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004255 if ((v < 0) ||
4256 (tempInt <= 0) ||
4257 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4258 {
4259 return -EINVAL;
4260 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004261 pChannelList[j] = tempInt;
4262
4263 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4264 "Channel %d added to preferred channel list",
4265 pChannelList[j] );
4266 }
4267
Srinivas Girigowdade697412013-02-14 16:31:48 -08004268 return VOS_STATUS_SUCCESS;
4269}
4270
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004271
4272/**---------------------------------------------------------------------------
4273
4274 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4275
4276 This function parses the reasoc command data passed in the format
4277 REASSOC<space><bssid><space><channel>
4278
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004279 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004280 \param - pTargetApBssid Pointer to target Ap bssid
4281 \param - pChannel Pointer to the Target AP channel
4282
4283 \return - 0 for success non-zero for failure
4284
4285 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004286VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4287 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004288{
4289 tANI_U8 *inPtr = pValue;
4290 int tempInt;
4291 int v = 0;
4292 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004293 /* 12 hexa decimal digits and 5 ':' */
4294 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004295
4296 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4297 /*no argument after the command*/
4298 if (NULL == inPtr)
4299 {
4300 return -EINVAL;
4301 }
4302
4303 /*no space after the command*/
4304 else if (SPACE_ASCII_VALUE != *inPtr)
4305 {
4306 return -EINVAL;
4307 }
4308
4309 /*removing empty spaces*/
4310 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4311
4312 /*no argument followed by spaces*/
4313 if ('\0' == *inPtr)
4314 {
4315 return -EINVAL;
4316 }
4317
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004318 v = sscanf(inPtr, "%17s", macAddress);
4319 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004320 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004321 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4322 "Invalid MAC address or All hex inputs are not read (%d)", v);
4323 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004324 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004325
4326 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4327 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4328 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4329 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4330 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4331 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004332
4333 /* point to the next argument */
4334 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4335 /*no argument after the command*/
4336 if (NULL == inPtr) return -EINVAL;
4337
4338 /*removing empty spaces*/
4339 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4340
4341 /*no argument followed by spaces*/
4342 if ('\0' == *inPtr)
4343 {
4344 return -EINVAL;
4345 }
4346
4347 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004348 v = sscanf(inPtr, "%32s ", tempBuf);
4349 if (1 != v) return -EINVAL;
4350
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004351 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004352 if ((v < 0) ||
4353 (tempInt <= 0) ||
4354 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4355 {
4356 return -EINVAL;
4357 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004358
4359 *pChannel = tempInt;
4360 return VOS_STATUS_SUCCESS;
4361}
4362
4363#endif
4364
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004365#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4366/**---------------------------------------------------------------------------
4367
4368 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4369
4370 This function parses the SETCCKM IE command
4371 SETCCKMIE<space><ie data>
4372
4373 \param - pValue Pointer to input data
4374 \param - pCckmIe Pointer to output cckm Ie
4375 \param - pCckmIeLen Pointer to output cckm ie length
4376
4377 \return - 0 for success non-zero for failure
4378
4379 --------------------------------------------------------------------------*/
4380VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4381 tANI_U8 *pCckmIeLen)
4382{
4383 tANI_U8 *inPtr = pValue;
4384 tANI_U8 *dataEnd;
4385 int j = 0;
4386 int i = 0;
4387 tANI_U8 tempByte = 0;
4388
4389 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4390 /*no argument after the command*/
4391 if (NULL == inPtr)
4392 {
4393 return -EINVAL;
4394 }
4395
4396 /*no space after the command*/
4397 else if (SPACE_ASCII_VALUE != *inPtr)
4398 {
4399 return -EINVAL;
4400 }
4401
4402 /*removing empty spaces*/
4403 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4404
4405 /*no argument followed by spaces*/
4406 if ('\0' == *inPtr)
4407 {
4408 return -EINVAL;
4409 }
4410
4411 /* find the length of data */
4412 dataEnd = inPtr;
4413 while(('\0' != *dataEnd) )
4414 {
4415 dataEnd++;
4416 ++(*pCckmIeLen);
4417 }
4418 if ( *pCckmIeLen <= 0) return -EINVAL;
4419
4420 /* Allocate the number of bytes based on the number of input characters
4421 whether it is even or odd.
4422 if the number of input characters are even, then we need N/2 byte.
4423 if the number of input characters are odd, then we need do (N+1)/2 to
4424 compensate rounding off.
4425 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4426 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4427 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4428 if (NULL == *pCckmIe)
4429 {
4430 hddLog(VOS_TRACE_LEVEL_FATAL,
4431 "%s: vos_mem_alloc failed ", __func__);
4432 return -EINVAL;
4433 }
4434 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4435 /* the buffer received from the upper layer is character buffer,
4436 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4437 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4438 and f0 in 3rd location */
4439 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4440 {
4441 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4442 (*pCckmIe)[i++] = tempByte;
4443 }
4444 *pCckmIeLen = i;
4445
4446 return VOS_STATUS_SUCCESS;
4447}
4448#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4449
Jeff Johnson295189b2012-06-20 16:38:30 -07004450/**---------------------------------------------------------------------------
4451
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004452 \brief hdd_is_valid_mac_address() - Validate MAC address
4453
4454 This function validates whether the given MAC address is valid or not
4455 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4456 where X is the hexa decimal digit character and separated by ':'
4457 This algorithm works even if MAC address is not separated by ':'
4458
4459 This code checks given input string mac contains exactly 12 hexadecimal digits.
4460 and a separator colon : appears in the input string only after
4461 an even number of hex digits.
4462
4463 \param - pMacAddr pointer to the input MAC address
4464 \return - 1 for valid and 0 for invalid
4465
4466 --------------------------------------------------------------------------*/
4467
4468v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4469{
4470 int xdigit = 0;
4471 int separator = 0;
4472 while (*pMacAddr)
4473 {
4474 if (isxdigit(*pMacAddr))
4475 {
4476 xdigit++;
4477 }
4478 else if (':' == *pMacAddr)
4479 {
4480 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4481 break;
4482
4483 ++separator;
4484 }
4485 else
4486 {
4487 separator = -1;
4488 /* Invalid MAC found */
4489 return 0;
4490 }
4491 ++pMacAddr;
4492 }
4493 return (xdigit == 12 && (separator == 5 || separator == 0));
4494}
4495
4496/**---------------------------------------------------------------------------
4497
Jeff Johnson295189b2012-06-20 16:38:30 -07004498 \brief hdd_open() - HDD Open function
4499
4500 This is called in response to ifconfig up
4501
4502 \param - dev Pointer to net_device structure
4503
4504 \return - 0 for success non-zero for failure
4505
4506 --------------------------------------------------------------------------*/
4507int hdd_open (struct net_device *dev)
4508{
4509 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4510 hdd_context_t *pHddCtx;
4511 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4512 VOS_STATUS status;
4513 v_BOOL_t in_standby = TRUE;
4514
4515 if (NULL == pAdapter)
4516 {
4517 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004518 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004519 return -ENODEV;
4520 }
4521
4522 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4523 if (NULL == pHddCtx)
4524 {
4525 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004526 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004527 return -ENODEV;
4528 }
4529
4530 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4531 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4532 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004533 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4534 {
4535 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304536 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004537 in_standby = FALSE;
4538 break;
4539 }
4540 else
4541 {
4542 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4543 pAdapterNode = pNext;
4544 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004545 }
4546
4547 if (TRUE == in_standby)
4548 {
4549 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4550 {
4551 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4552 "wlan out of power save", __func__);
4553 return -EINVAL;
4554 }
4555 }
4556
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004557 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004558 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4559 {
4560 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004561 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004562 /* Enable TX queues only when we are connected */
4563 netif_tx_start_all_queues(dev);
4564 }
4565
4566 return 0;
4567}
4568
4569int hdd_mon_open (struct net_device *dev)
4570{
4571 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4572
4573 if(pAdapter == NULL) {
4574 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004575 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004576 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004577 }
4578
4579 netif_start_queue(dev);
4580
4581 return 0;
4582}
4583/**---------------------------------------------------------------------------
4584
4585 \brief hdd_stop() - HDD stop function
4586
4587 This is called in response to ifconfig down
4588
4589 \param - dev Pointer to net_device structure
4590
4591 \return - 0 for success non-zero for failure
4592
4593 --------------------------------------------------------------------------*/
4594
4595int hdd_stop (struct net_device *dev)
4596{
4597 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4598 hdd_context_t *pHddCtx;
4599 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4600 VOS_STATUS status;
4601 v_BOOL_t enter_standby = TRUE;
4602
4603 ENTER();
4604
4605 if (NULL == pAdapter)
4606 {
4607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004608 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004609 return -ENODEV;
4610 }
4611
4612 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4613 if (NULL == pHddCtx)
4614 {
4615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004616 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004617 return -ENODEV;
4618 }
4619
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004620 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004621 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4622 netif_tx_disable(pAdapter->dev);
4623 netif_carrier_off(pAdapter->dev);
4624
4625
4626 /* SoftAP ifaces should never go in power save mode
4627 making sure same here. */
4628 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4629 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004631 )
4632 {
4633 /* SoftAP mode, so return from here */
4634 EXIT();
4635 return 0;
4636 }
4637
4638 /* Find if any iface is up then
4639 if any iface is up then can't put device to sleep/ power save mode. */
4640 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4641 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4642 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004643 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4644 {
4645 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304646 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004647 enter_standby = FALSE;
4648 break;
4649 }
4650 else
4651 {
4652 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4653 pAdapterNode = pNext;
4654 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004655 }
4656
4657 if (TRUE == enter_standby)
4658 {
4659 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4660 "entering standby", __func__);
4661 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4662 {
4663 /*log and return success*/
4664 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4665 "wlan in power save", __func__);
4666 }
4667 }
4668
4669 EXIT();
4670 return 0;
4671}
4672
4673/**---------------------------------------------------------------------------
4674
4675 \brief hdd_uninit() - HDD uninit function
4676
4677 This is called during the netdev unregister to uninitialize all data
4678associated with the device
4679
4680 \param - dev Pointer to net_device structure
4681
4682 \return - void
4683
4684 --------------------------------------------------------------------------*/
4685static void hdd_uninit (struct net_device *dev)
4686{
4687 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4688
4689 ENTER();
4690
4691 do
4692 {
4693 if (NULL == pAdapter)
4694 {
4695 hddLog(VOS_TRACE_LEVEL_FATAL,
4696 "%s: NULL pAdapter", __func__);
4697 break;
4698 }
4699
4700 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4701 {
4702 hddLog(VOS_TRACE_LEVEL_FATAL,
4703 "%s: Invalid magic", __func__);
4704 break;
4705 }
4706
4707 if (NULL == pAdapter->pHddCtx)
4708 {
4709 hddLog(VOS_TRACE_LEVEL_FATAL,
4710 "%s: NULL pHddCtx", __func__);
4711 break;
4712 }
4713
4714 if (dev != pAdapter->dev)
4715 {
4716 hddLog(VOS_TRACE_LEVEL_FATAL,
4717 "%s: Invalid device reference", __func__);
4718 /* we haven't validated all cases so let this go for now */
4719 }
4720
4721 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4722
4723 /* after uninit our adapter structure will no longer be valid */
4724 pAdapter->dev = NULL;
4725 pAdapter->magic = 0;
4726 } while (0);
4727
4728 EXIT();
4729}
4730
4731/**---------------------------------------------------------------------------
4732
4733 \brief hdd_release_firmware() -
4734
4735 This function calls the release firmware API to free the firmware buffer.
4736
4737 \param - pFileName Pointer to the File Name.
4738 pCtx - Pointer to the adapter .
4739
4740
4741 \return - 0 for success, non zero for failure
4742
4743 --------------------------------------------------------------------------*/
4744
4745VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4746{
4747 VOS_STATUS status = VOS_STATUS_SUCCESS;
4748 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4749 ENTER();
4750
4751
4752 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4753
4754 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4755
4756 if(pHddCtx->fw) {
4757 release_firmware(pHddCtx->fw);
4758 pHddCtx->fw = NULL;
4759 }
4760 else
4761 status = VOS_STATUS_E_FAILURE;
4762 }
4763 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4764 if(pHddCtx->nv) {
4765 release_firmware(pHddCtx->nv);
4766 pHddCtx->nv = NULL;
4767 }
4768 else
4769 status = VOS_STATUS_E_FAILURE;
4770
4771 }
4772
4773 EXIT();
4774 return status;
4775}
4776
4777/**---------------------------------------------------------------------------
4778
4779 \brief hdd_request_firmware() -
4780
4781 This function reads the firmware file using the request firmware
4782 API and returns the the firmware data and the firmware file size.
4783
4784 \param - pfileName - Pointer to the file name.
4785 - pCtx - Pointer to the adapter .
4786 - ppfw_data - Pointer to the pointer of the firmware data.
4787 - pSize - Pointer to the file size.
4788
4789 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4790
4791 --------------------------------------------------------------------------*/
4792
4793
4794VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4795{
4796 int status;
4797 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4798 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4799 ENTER();
4800
4801 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4802
4803 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4804
4805 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4806 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4807 __func__, pfileName);
4808 retval = VOS_STATUS_E_FAILURE;
4809 }
4810
4811 else {
4812 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4813 *pSize = pHddCtx->fw->size;
4814 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4815 __func__, *pSize);
4816 }
4817 }
4818 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4819
4820 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4821
4822 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4823 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4824 __func__, pfileName);
4825 retval = VOS_STATUS_E_FAILURE;
4826 }
4827
4828 else {
4829 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4830 *pSize = pHddCtx->nv->size;
4831 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4832 __func__, *pSize);
4833 }
4834 }
4835
4836 EXIT();
4837 return retval;
4838}
4839/**---------------------------------------------------------------------------
4840 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4841
4842 This is the function invoked by SME to inform the result of a full power
4843 request issued by HDD
4844
4845 \param - callbackcontext - Pointer to cookie
4846 status - result of request
4847
4848 \return - None
4849
4850--------------------------------------------------------------------------*/
4851void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4852{
4853 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4854
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004855 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004856 if(&pHddCtx->full_pwr_comp_var)
4857 {
4858 complete(&pHddCtx->full_pwr_comp_var);
4859 }
4860}
4861
4862/**---------------------------------------------------------------------------
4863
4864 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4865
4866 This is the function invoked by SME to inform the result of BMPS
4867 request issued by HDD
4868
4869 \param - callbackcontext - Pointer to cookie
4870 status - result of request
4871
4872 \return - None
4873
4874--------------------------------------------------------------------------*/
4875void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4876{
4877
4878 struct completion *completion_var = (struct completion*) callbackContext;
4879
Arif Hussain6d2a3322013-11-17 19:50:10 -08004880 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004881 if(completion_var != NULL)
4882 {
4883 complete(completion_var);
4884 }
4885}
4886
4887/**---------------------------------------------------------------------------
4888
4889 \brief hdd_get_cfg_file_size() -
4890
4891 This function reads the configuration file using the request firmware
4892 API and returns the configuration file size.
4893
4894 \param - pCtx - Pointer to the adapter .
4895 - pFileName - Pointer to the file name.
4896 - pBufSize - Pointer to the buffer size.
4897
4898 \return - 0 for success, non zero for failure
4899
4900 --------------------------------------------------------------------------*/
4901
4902VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4903{
4904 int status;
4905 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4906
4907 ENTER();
4908
4909 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4910
4911 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4912 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4913 status = VOS_STATUS_E_FAILURE;
4914 }
4915 else {
4916 *pBufSize = pHddCtx->fw->size;
4917 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4918 release_firmware(pHddCtx->fw);
4919 pHddCtx->fw = NULL;
4920 }
4921
4922 EXIT();
4923 return VOS_STATUS_SUCCESS;
4924}
4925
4926/**---------------------------------------------------------------------------
4927
4928 \brief hdd_read_cfg_file() -
4929
4930 This function reads the configuration file using the request firmware
4931 API and returns the cfg data and the buffer size of the configuration file.
4932
4933 \param - pCtx - Pointer to the adapter .
4934 - pFileName - Pointer to the file name.
4935 - pBuffer - Pointer to the data buffer.
4936 - pBufSize - Pointer to the buffer size.
4937
4938 \return - 0 for success, non zero for failure
4939
4940 --------------------------------------------------------------------------*/
4941
4942VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4943 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4944{
4945 int status;
4946 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4947
4948 ENTER();
4949
4950 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4951
4952 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4953 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4954 return VOS_STATUS_E_FAILURE;
4955 }
4956 else {
4957 if(*pBufSize != pHddCtx->fw->size) {
4958 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4959 "file size", __func__);
4960 release_firmware(pHddCtx->fw);
4961 pHddCtx->fw = NULL;
4962 return VOS_STATUS_E_FAILURE;
4963 }
4964 else {
4965 if(pBuffer) {
4966 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4967 }
4968 release_firmware(pHddCtx->fw);
4969 pHddCtx->fw = NULL;
4970 }
4971 }
4972
4973 EXIT();
4974
4975 return VOS_STATUS_SUCCESS;
4976}
4977
4978/**---------------------------------------------------------------------------
4979
Jeff Johnson295189b2012-06-20 16:38:30 -07004980 \brief hdd_set_mac_address() -
4981
4982 This function sets the user specified mac address using
4983 the command ifconfig wlanX hw ether <mac adress>.
4984
4985 \param - dev - Pointer to the net device.
4986 - addr - Pointer to the sockaddr.
4987 \return - 0 for success, non zero for failure
4988
4989 --------------------------------------------------------------------------*/
4990
4991static int hdd_set_mac_address(struct net_device *dev, void *addr)
4992{
4993 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4994 struct sockaddr *psta_mac_addr = addr;
4995 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4996
4997 ENTER();
4998
4999 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5000
5001#ifdef HDD_SESSIONIZE
5002 // set the MAC address though the STA ID CFG.
5003 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5004 (v_U8_t *)&pAdapter->macAddressCurrent,
5005 sizeof( pAdapter->macAddressCurrent ),
5006 hdd_set_mac_addr_cb, VOS_FALSE );
5007#endif
5008
5009 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5010
5011 EXIT();
5012 return halStatus;
5013}
5014
5015tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5016{
5017 int i;
5018 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5019 {
5020 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5021 break;
5022 }
5023
5024 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5025 return NULL;
5026
5027 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5028 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5029}
5030
5031void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5032{
5033 int i;
5034 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5035 {
5036 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5037 {
5038 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5039 break;
5040 }
5041 }
5042 return;
5043}
5044
5045#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5046 static struct net_device_ops wlan_drv_ops = {
5047 .ndo_open = hdd_open,
5048 .ndo_stop = hdd_stop,
5049 .ndo_uninit = hdd_uninit,
5050 .ndo_start_xmit = hdd_hard_start_xmit,
5051 .ndo_tx_timeout = hdd_tx_timeout,
5052 .ndo_get_stats = hdd_stats,
5053 .ndo_do_ioctl = hdd_ioctl,
5054 .ndo_set_mac_address = hdd_set_mac_address,
5055 .ndo_select_queue = hdd_select_queue,
5056#ifdef WLAN_FEATURE_PACKET_FILTERING
5057#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5058 .ndo_set_rx_mode = hdd_set_multicast_list,
5059#else
5060 .ndo_set_multicast_list = hdd_set_multicast_list,
5061#endif //LINUX_VERSION_CODE
5062#endif
5063 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005064 static struct net_device_ops wlan_mon_drv_ops = {
5065 .ndo_open = hdd_mon_open,
5066 .ndo_stop = hdd_stop,
5067 .ndo_uninit = hdd_uninit,
5068 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5069 .ndo_tx_timeout = hdd_tx_timeout,
5070 .ndo_get_stats = hdd_stats,
5071 .ndo_do_ioctl = hdd_ioctl,
5072 .ndo_set_mac_address = hdd_set_mac_address,
5073 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005074
5075#endif
5076
5077void hdd_set_station_ops( struct net_device *pWlanDev )
5078{
5079#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005080 pWlanDev->netdev_ops = &wlan_drv_ops;
5081#else
5082 pWlanDev->open = hdd_open;
5083 pWlanDev->stop = hdd_stop;
5084 pWlanDev->uninit = hdd_uninit;
5085 pWlanDev->hard_start_xmit = NULL;
5086 pWlanDev->tx_timeout = hdd_tx_timeout;
5087 pWlanDev->get_stats = hdd_stats;
5088 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005089 pWlanDev->set_mac_address = hdd_set_mac_address;
5090#endif
5091}
5092
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005093static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005094{
5095 struct net_device *pWlanDev = NULL;
5096 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005097 /*
5098 * cfg80211 initialization and registration....
5099 */
5100 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5101
Jeff Johnson295189b2012-06-20 16:38:30 -07005102 if(pWlanDev != NULL)
5103 {
5104
5105 //Save the pointer to the net_device in the HDD adapter
5106 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5107
Jeff Johnson295189b2012-06-20 16:38:30 -07005108 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5109
5110 pAdapter->dev = pWlanDev;
5111 pAdapter->pHddCtx = pHddCtx;
5112 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5113
5114 init_completion(&pAdapter->session_open_comp_var);
5115 init_completion(&pAdapter->session_close_comp_var);
5116 init_completion(&pAdapter->disconnect_comp_var);
5117 init_completion(&pAdapter->linkup_event_var);
5118 init_completion(&pAdapter->cancel_rem_on_chan_var);
5119 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005120#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5121 init_completion(&pAdapter->offchannel_tx_event);
5122#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005123 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005124#ifdef FEATURE_WLAN_TDLS
5125 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005126 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005127 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305128 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005129#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005130 init_completion(&pHddCtx->mc_sus_event_var);
5131 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305132 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005133 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005134 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005135
Rajeev79dbe4c2013-10-05 11:03:42 +05305136#ifdef FEATURE_WLAN_BATCH_SCAN
5137 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5138 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5139 pAdapter->pBatchScanRsp = NULL;
5140 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005141 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08005142 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305143 mutex_init(&pAdapter->hdd_batch_scan_lock);
5144#endif
5145
Jeff Johnson295189b2012-06-20 16:38:30 -07005146 pAdapter->isLinkUpSvcNeeded = FALSE;
5147 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5148 //Init the net_device structure
5149 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5150
5151 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5152 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5153 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5154 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5155
5156 hdd_set_station_ops( pAdapter->dev );
5157
5158 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005159 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5160 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5161 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005162 /* set pWlanDev's parent to underlying device */
5163 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5164 }
5165
5166 return pAdapter;
5167}
5168
5169VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5170{
5171 struct net_device *pWlanDev = pAdapter->dev;
5172 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5173 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5174 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5175
5176 if( rtnl_lock_held )
5177 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005178 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005179 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5180 {
5181 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5182 return VOS_STATUS_E_FAILURE;
5183 }
5184 }
5185 if (register_netdevice(pWlanDev))
5186 {
5187 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5188 return VOS_STATUS_E_FAILURE;
5189 }
5190 }
5191 else
5192 {
5193 if(register_netdev(pWlanDev))
5194 {
5195 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5196 return VOS_STATUS_E_FAILURE;
5197 }
5198 }
5199 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5200
5201 return VOS_STATUS_SUCCESS;
5202}
5203
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005204static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005205{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005206 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005207
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005208 if (NULL == pAdapter)
5209 {
5210 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5211 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005212 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005213
5214 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5215 {
5216 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5217 return eHAL_STATUS_NOT_INITIALIZED;
5218 }
5219
5220 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5221
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005222#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005223 /* need to make sure all of our scheduled work has completed.
5224 * This callback is called from MC thread context, so it is safe to
5225 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005226 *
5227 * Even though this is called from MC thread context, if there is a faulty
5228 * work item in the system, that can hang this call forever. So flushing
5229 * this global work queue is not safe; and now we make sure that
5230 * individual work queues are stopped correctly. But the cancel work queue
5231 * is a GPL only API, so the proprietary version of the driver would still
5232 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005233 */
5234 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005235#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005236
5237 /* We can be blocked while waiting for scheduled work to be
5238 * flushed, and the adapter structure can potentially be freed, in
5239 * which case the magic will have been reset. So make sure the
5240 * magic is still good, and hence the adapter structure is still
5241 * valid, before signaling completion */
5242 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5243 {
5244 complete(&pAdapter->session_close_comp_var);
5245 }
5246
Jeff Johnson295189b2012-06-20 16:38:30 -07005247 return eHAL_STATUS_SUCCESS;
5248}
5249
5250VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5251{
5252 struct net_device *pWlanDev = pAdapter->dev;
5253 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5254 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5255 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5256 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5257 int rc = 0;
5258
5259 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005260 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005261 //Open a SME session for future operation
5262 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005263 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005264 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5265 {
5266 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005267 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005268 halStatus, halStatus );
5269 status = VOS_STATUS_E_FAILURE;
5270 goto error_sme_open;
5271 }
5272
5273 //Block on a completion variable. Can't wait forever though.
5274 rc = wait_for_completion_interruptible_timeout(
5275 &pAdapter->session_open_comp_var,
5276 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5277 if (!rc)
5278 {
5279 hddLog(VOS_TRACE_LEVEL_FATAL,
5280 "Session is not opened within timeout period code %08d", rc );
5281 status = VOS_STATUS_E_FAILURE;
5282 goto error_sme_open;
5283 }
5284
5285 // Register wireless extensions
5286 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5287 {
5288 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005289 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 halStatus, halStatus );
5291 status = VOS_STATUS_E_FAILURE;
5292 goto error_register_wext;
5293 }
5294 //Safe to register the hard_start_xmit function again
5295#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5296 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5297#else
5298 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5299#endif
5300
5301 //Set the Connection State to Not Connected
5302 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5303
5304 //Set the default operation channel
5305 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5306
5307 /* Make the default Auth Type as OPEN*/
5308 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5309
5310 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5311 {
5312 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005313 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005314 status, status );
5315 goto error_init_txrx;
5316 }
5317
5318 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5319
5320 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5321 {
5322 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005323 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005324 status, status );
5325 goto error_wmm_init;
5326 }
5327
5328 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5329
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005330#ifdef FEATURE_WLAN_TDLS
5331 if(0 != wlan_hdd_tdls_init(pAdapter))
5332 {
5333 status = VOS_STATUS_E_FAILURE;
5334 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5335 goto error_tdls_init;
5336 }
5337 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5338#endif
5339
Jeff Johnson295189b2012-06-20 16:38:30 -07005340 return VOS_STATUS_SUCCESS;
5341
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005342#ifdef FEATURE_WLAN_TDLS
5343error_tdls_init:
5344 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5345 hdd_wmm_adapter_close(pAdapter);
5346#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005347error_wmm_init:
5348 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5349 hdd_deinit_tx_rx(pAdapter);
5350error_init_txrx:
5351 hdd_UnregisterWext(pWlanDev);
5352error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005353 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005354 {
5355 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005356 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005357 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005358 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005359 {
5360 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005361 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005362 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005363 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005364 }
5365}
5366error_sme_open:
5367 return status;
5368}
5369
Jeff Johnson295189b2012-06-20 16:38:30 -07005370void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5371{
5372 hdd_cfg80211_state_t *cfgState;
5373
5374 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5375
5376 if( NULL != cfgState->buf )
5377 {
5378 int rc;
5379 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5380 rc = wait_for_completion_interruptible_timeout(
5381 &pAdapter->tx_action_cnf_event,
5382 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5383 if(!rc)
5384 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005385 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005386 ("ERROR: HDD Wait for Action Confirmation Failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07005387 }
5388 }
5389 return;
5390}
Jeff Johnson295189b2012-06-20 16:38:30 -07005391
5392void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5393{
5394 ENTER();
5395 switch ( pAdapter->device_mode )
5396 {
5397 case WLAN_HDD_INFRA_STATION:
5398 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005399 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005400 {
5401 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5402 {
5403 hdd_deinit_tx_rx( pAdapter );
5404 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5405 }
5406
5407 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5408 {
5409 hdd_wmm_adapter_close( pAdapter );
5410 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5411 }
5412
Jeff Johnson295189b2012-06-20 16:38:30 -07005413 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005414#ifdef FEATURE_WLAN_TDLS
5415 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5416 {
5417 wlan_hdd_tdls_exit(pAdapter);
5418 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5419 }
5420#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005421
5422 break;
5423 }
5424
5425 case WLAN_HDD_SOFTAP:
5426 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005427 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305428
5429 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5430 {
5431 hdd_wmm_adapter_close( pAdapter );
5432 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5433 }
5434
Jeff Johnson295189b2012-06-20 16:38:30 -07005435 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005436
5437 hdd_unregister_hostapd(pAdapter);
5438 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005439 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005440 break;
5441 }
5442
5443 case WLAN_HDD_MONITOR:
5444 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005445 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005446 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5447 {
5448 hdd_deinit_tx_rx( pAdapter );
5449 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5450 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005451 if(NULL != pAdapterforTx)
5452 {
5453 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5454 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005455 break;
5456 }
5457
5458
5459 default:
5460 break;
5461 }
5462
5463 EXIT();
5464}
5465
5466void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5467{
5468 struct net_device *pWlanDev = pAdapter->dev;
5469
Rajeev79dbe4c2013-10-05 11:03:42 +05305470#ifdef FEATURE_WLAN_BATCH_SCAN
5471 tHddBatchScanRsp *pNode;
5472 tHddBatchScanRsp *pPrev;
5473 if (pAdapter)
5474 {
Rajeev79dbe4c2013-10-05 11:03:42 +05305475 pNode = pAdapter->pBatchScanRsp;
5476 while (pNode)
5477 {
5478 pPrev = pNode;
5479 pNode = pNode->pNext;
5480 vos_mem_free((v_VOID_t * )pPrev);
5481 }
5482 pAdapter->pBatchScanRsp = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05305483 }
5484#endif
5485
Jeff Johnson295189b2012-06-20 16:38:30 -07005486 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5487 if( rtnl_held )
5488 {
5489 unregister_netdevice(pWlanDev);
5490 }
5491 else
5492 {
5493 unregister_netdev(pWlanDev);
5494 }
5495 // note that the pAdapter is no longer valid at this point
5496 // since the memory has been reclaimed
5497 }
5498
5499}
5500
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005501void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5502{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305503 VOS_STATUS status;
5504 hdd_adapter_t *pAdapter = NULL;
5505 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005506
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305507 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005508
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305509 /*loop through all adapters.*/
5510 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005511 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305512 pAdapter = pAdapterNode->pAdapter;
5513 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5514 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005515
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305516 { // we skip this registration for modes other than STA and P2P client modes.
5517 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5518 pAdapterNode = pNext;
5519 continue;
5520 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005521
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305522 //Apply Dynamic DTIM For P2P
5523 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5524 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5525 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5526 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5527 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5528 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5529 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5530 (eConnectionState_Associated ==
5531 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5532 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5533 {
5534 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005535
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305536 powerRequest.uIgnoreDTIM = 1;
5537 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5538
5539 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5540 {
5541 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5542 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5543 }
5544 else
5545 {
5546 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5547 }
5548
5549 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5550 * specified during Enter/Exit BMPS when LCD off*/
5551 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5552 NULL, eANI_BOOLEAN_FALSE);
5553 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5554 NULL, eANI_BOOLEAN_FALSE);
5555
5556 /* switch to the DTIM specified in cfg.ini */
5557 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5558 "Switch to DTIM %d", powerRequest.uListenInterval);
5559 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5560 break;
5561
5562 }
5563
5564 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5565 pAdapterNode = pNext;
5566 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005567}
5568
5569void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5570{
5571 /*Switch back to DTIM 1*/
5572 tSirSetPowerParamsReq powerRequest = { 0 };
5573
5574 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5575 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005576 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005577
5578 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5579 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5580 NULL, eANI_BOOLEAN_FALSE);
5581 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5582 NULL, eANI_BOOLEAN_FALSE);
5583
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
5588}
5589
Jeff Johnson295189b2012-06-20 16:38:30 -07005590VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5591{
5592 VOS_STATUS status = VOS_STATUS_SUCCESS;
5593
5594 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5595 {
5596 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5597 }
5598
5599 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5600 {
5601 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5602 }
5603
5604 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5605 {
5606 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5607 }
5608
5609 return status;
5610}
5611
5612VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5613{
5614 hdd_adapter_t *pAdapter = NULL;
5615 eHalStatus halStatus;
5616 VOS_STATUS status = VOS_STATUS_E_INVAL;
5617 v_BOOL_t disableBmps = FALSE;
5618 v_BOOL_t disableImps = FALSE;
5619
5620 switch(session_type)
5621 {
5622 case WLAN_HDD_INFRA_STATION:
5623 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005624 case WLAN_HDD_P2P_CLIENT:
5625 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005626 //Exit BMPS -> Is Sta/P2P Client is already connected
5627 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5628 if((NULL != pAdapter)&&
5629 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5630 {
5631 disableBmps = TRUE;
5632 }
5633
5634 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5635 if((NULL != pAdapter)&&
5636 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5637 {
5638 disableBmps = TRUE;
5639 }
5640
5641 //Exit both Bmps and Imps incase of Go/SAP Mode
5642 if((WLAN_HDD_SOFTAP == session_type) ||
5643 (WLAN_HDD_P2P_GO == session_type))
5644 {
5645 disableBmps = TRUE;
5646 disableImps = TRUE;
5647 }
5648
5649 if(TRUE == disableImps)
5650 {
5651 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5652 {
5653 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5654 }
5655 }
5656
5657 if(TRUE == disableBmps)
5658 {
5659 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5660 {
5661 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5662
5663 if(eHAL_STATUS_SUCCESS != halStatus)
5664 {
5665 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005666 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005667 VOS_ASSERT(0);
5668 return status;
5669 }
5670 }
5671
5672 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5673 {
5674 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5675
5676 if(eHAL_STATUS_SUCCESS != halStatus)
5677 {
5678 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005679 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005680 VOS_ASSERT(0);
5681 return status;
5682 }
5683 }
5684 }
5685
5686 if((TRUE == disableBmps) ||
5687 (TRUE == disableImps))
5688 {
5689 /* Now, get the chip into Full Power now */
5690 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5691 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5692 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5693
5694 if(halStatus != eHAL_STATUS_SUCCESS)
5695 {
5696 if(halStatus == eHAL_STATUS_PMC_PENDING)
5697 {
5698 //Block on a completion variable. Can't wait forever though
5699 wait_for_completion_interruptible_timeout(
5700 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5701 }
5702 else
5703 {
5704 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005705 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005706 VOS_ASSERT(0);
5707 return status;
5708 }
5709 }
5710
5711 status = VOS_STATUS_SUCCESS;
5712 }
5713
5714 break;
5715 }
5716 return status;
5717}
5718
5719hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005720 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005721 tANI_U8 rtnl_held )
5722{
5723 hdd_adapter_t *pAdapter = NULL;
5724 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5725 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5726 VOS_STATUS exitbmpsStatus;
5727
Arif Hussain6d2a3322013-11-17 19:50:10 -08005728 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005729
5730 //Disable BMPS incase of Concurrency
5731 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5732
5733 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5734 {
5735 //Fail to Exit BMPS
5736 VOS_ASSERT(0);
5737 return NULL;
5738 }
5739
5740 switch(session_type)
5741 {
5742 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005743 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005744 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005745 {
5746 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5747
5748 if( NULL == pAdapter )
5749 return NULL;
5750
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305751#ifdef FEATURE_WLAN_TDLS
5752 /* A Mutex Lock is introduced while changing/initializing the mode to
5753 * protect the concurrent access for the Adapters by TDLS module.
5754 */
5755 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5756 {
5757 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5758 "%s: unable to lock list", __func__);
5759 return NULL;
5760 }
5761#endif
5762
Jeff Johnsone7245742012-09-05 17:12:55 -07005763 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5764 NL80211_IFTYPE_P2P_CLIENT:
5765 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005766
Jeff Johnson295189b2012-06-20 16:38:30 -07005767 pAdapter->device_mode = session_type;
5768
5769 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305770#ifdef FEATURE_WLAN_TDLS
5771 mutex_unlock(&pHddCtx->tdls_lock);
5772#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005773 if( VOS_STATUS_SUCCESS != status )
5774 goto err_free_netdev;
5775
5776 status = hdd_register_interface( pAdapter, rtnl_held );
5777 if( VOS_STATUS_SUCCESS != status )
5778 {
5779 hdd_deinit_adapter(pHddCtx, pAdapter);
5780 goto err_free_netdev;
5781 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305782
5783#ifdef WLAN_NS_OFFLOAD
5784 // Workqueue which gets scheduled in IPv6 notification callback.
5785 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5786#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005787 //Stop the Interface TX queue.
5788 netif_tx_disable(pAdapter->dev);
5789 //netif_tx_disable(pWlanDev);
5790 netif_carrier_off(pAdapter->dev);
5791
5792 break;
5793 }
5794
Jeff Johnson295189b2012-06-20 16:38:30 -07005795 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005796 case WLAN_HDD_SOFTAP:
5797 {
5798 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5799 if( NULL == pAdapter )
5800 return NULL;
5801
Jeff Johnson295189b2012-06-20 16:38:30 -07005802 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5803 NL80211_IFTYPE_AP:
5804 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 pAdapter->device_mode = session_type;
5806
5807 status = hdd_init_ap_mode(pAdapter);
5808 if( VOS_STATUS_SUCCESS != status )
5809 goto err_free_netdev;
5810
5811 status = hdd_register_hostapd( pAdapter, rtnl_held );
5812 if( VOS_STATUS_SUCCESS != status )
5813 {
5814 hdd_deinit_adapter(pHddCtx, pAdapter);
5815 goto err_free_netdev;
5816 }
5817
5818 netif_tx_disable(pAdapter->dev);
5819 netif_carrier_off(pAdapter->dev);
5820
5821 hdd_set_conparam( 1 );
5822 break;
5823 }
5824 case WLAN_HDD_MONITOR:
5825 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005826 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5827 if( NULL == pAdapter )
5828 return NULL;
5829
5830 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5831 pAdapter->device_mode = session_type;
5832 status = hdd_register_interface( pAdapter, rtnl_held );
5833#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5834 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5835#else
5836 pAdapter->dev->open = hdd_mon_open;
5837 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5838#endif
5839 hdd_init_tx_rx( pAdapter );
5840 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5841 //Set adapter to be used for data tx. It will use either GO or softap.
5842 pAdapter->sessionCtx.monitor.pAdapterForTx =
5843 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005844 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5845 {
5846 pAdapter->sessionCtx.monitor.pAdapterForTx =
5847 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5848 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005849 /* This workqueue will be used to transmit management packet over
5850 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005851 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5852 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5853 return NULL;
5854 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005855
Jeff Johnson295189b2012-06-20 16:38:30 -07005856 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5857 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005858 }
5859 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005860 case WLAN_HDD_FTM:
5861 {
5862 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5863
5864 if( NULL == pAdapter )
5865 return NULL;
5866 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5867 * message while loading driver in FTM mode. */
5868 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5869 pAdapter->device_mode = session_type;
5870 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305871
5872 hdd_init_tx_rx( pAdapter );
5873
5874 //Stop the Interface TX queue.
5875 netif_tx_disable(pAdapter->dev);
5876 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005877 }
5878 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005879 default:
5880 {
5881 VOS_ASSERT(0);
5882 return NULL;
5883 }
5884 }
5885
Jeff Johnson295189b2012-06-20 16:38:30 -07005886 if( VOS_STATUS_SUCCESS == status )
5887 {
5888 //Add it to the hdd's session list.
5889 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5890 if( NULL == pHddAdapterNode )
5891 {
5892 status = VOS_STATUS_E_NOMEM;
5893 }
5894 else
5895 {
5896 pHddAdapterNode->pAdapter = pAdapter;
5897 status = hdd_add_adapter_back ( pHddCtx,
5898 pHddAdapterNode );
5899 }
5900 }
5901
5902 if( VOS_STATUS_SUCCESS != status )
5903 {
5904 if( NULL != pAdapter )
5905 {
5906 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5907 pAdapter = NULL;
5908 }
5909 if( NULL != pHddAdapterNode )
5910 {
5911 vos_mem_free( pHddAdapterNode );
5912 }
5913
5914 goto resume_bmps;
5915 }
5916
5917 if(VOS_STATUS_SUCCESS == status)
5918 {
5919 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5920
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005921 //Initialize the WoWL service
5922 if(!hdd_init_wowl(pAdapter))
5923 {
5924 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5925 goto err_free_netdev;
5926 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005927 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005928 return pAdapter;
5929
5930err_free_netdev:
5931 free_netdev(pAdapter->dev);
5932 wlan_hdd_release_intf_addr( pHddCtx,
5933 pAdapter->macAddressCurrent.bytes );
5934
5935resume_bmps:
5936 //If bmps disabled enable it
5937 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5938 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305939 if (pHddCtx->hdd_wlan_suspended)
5940 {
5941 hdd_set_pwrparams(pHddCtx);
5942 }
5943 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005944 }
5945 return NULL;
5946}
5947
5948VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5949 tANI_U8 rtnl_held )
5950{
5951 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5952 VOS_STATUS status;
5953
5954 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5955 if( VOS_STATUS_SUCCESS != status )
5956 return status;
5957
5958 while ( pCurrent->pAdapter != pAdapter )
5959 {
5960 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5961 if( VOS_STATUS_SUCCESS != status )
5962 break;
5963
5964 pCurrent = pNext;
5965 }
5966 pAdapterNode = pCurrent;
5967 if( VOS_STATUS_SUCCESS == status )
5968 {
5969 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5970 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305971
5972#ifdef FEATURE_WLAN_TDLS
5973
5974 /* A Mutex Lock is introduced while changing/initializing the mode to
5975 * protect the concurrent access for the Adapters by TDLS module.
5976 */
5977 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5978 {
5979 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5980 "%s: unable to lock list", __func__);
5981 return VOS_STATUS_E_FAILURE;
5982 }
5983#endif
5984
Jeff Johnson295189b2012-06-20 16:38:30 -07005985 hdd_remove_adapter( pHddCtx, pAdapterNode );
5986 vos_mem_free( pAdapterNode );
5987
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305988#ifdef FEATURE_WLAN_TDLS
5989 mutex_unlock(&pHddCtx->tdls_lock);
5990#endif
5991
Jeff Johnson295189b2012-06-20 16:38:30 -07005992
5993 /* If there is a single session of STA/P2P client, re-enable BMPS */
5994 if ((!vos_concurrent_sessions_running()) &&
5995 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5996 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
5997 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305998 if (pHddCtx->hdd_wlan_suspended)
5999 {
6000 hdd_set_pwrparams(pHddCtx);
6001 }
6002 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006003 }
6004
6005 return VOS_STATUS_SUCCESS;
6006 }
6007
6008 return VOS_STATUS_E_FAILURE;
6009}
6010
6011VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6012{
6013 hdd_adapter_list_node_t *pHddAdapterNode;
6014 VOS_STATUS status;
6015
6016 ENTER();
6017
6018 do
6019 {
6020 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6021 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6022 {
6023 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6024 vos_mem_free( pHddAdapterNode );
6025 }
6026 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6027
6028 EXIT();
6029
6030 return VOS_STATUS_SUCCESS;
6031}
6032
6033void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6034{
6035 v_U8_t addIE[1] = {0};
6036
6037 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6038 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6039 eANI_BOOLEAN_FALSE) )
6040 {
6041 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006042 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006043 }
6044
6045 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6046 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6047 eANI_BOOLEAN_FALSE) )
6048 {
6049 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006050 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006051 }
6052
6053 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6054 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6055 eANI_BOOLEAN_FALSE) )
6056 {
6057 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006058 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006059 }
6060}
6061
6062VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6063{
6064 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6065 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6066 union iwreq_data wrqu;
6067
6068 ENTER();
6069
6070 switch(pAdapter->device_mode)
6071 {
6072 case WLAN_HDD_INFRA_STATION:
6073 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006074 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006075 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6076 {
6077 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6078 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6079 pAdapter->sessionId,
6080 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6081 else
6082 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6083 pAdapter->sessionId,
6084 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6085 //success implies disconnect command got queued up successfully
6086 if(halStatus == eHAL_STATUS_SUCCESS)
6087 {
6088 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6089 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6090 }
6091 memset(&wrqu, '\0', sizeof(wrqu));
6092 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6093 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6094 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6095 }
6096 else
6097 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306098 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006099 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306100#ifdef WLAN_OPEN_SOURCE
6101#ifdef WLAN_NS_OFFLOAD
6102 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6103#endif
6104#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006105
6106 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6107 {
6108 INIT_COMPLETION(pAdapter->session_close_comp_var);
6109 if (eHAL_STATUS_SUCCESS ==
6110 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6111 hdd_smeCloseSessionCallback, pAdapter))
6112 {
6113 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006114 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006115 &pAdapter->session_close_comp_var,
6116 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6117 }
6118 }
6119
6120 break;
6121
6122 case WLAN_HDD_SOFTAP:
6123 case WLAN_HDD_P2P_GO:
6124 //Any softap specific cleanup here...
6125 mutex_lock(&pHddCtx->sap_lock);
6126 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6127 {
6128 VOS_STATUS status;
6129 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6130
6131 //Stop Bss.
6132 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6133 if (VOS_IS_STATUS_SUCCESS(status))
6134 {
6135 hdd_hostapd_state_t *pHostapdState =
6136 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6137
6138 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6139
6140 if (!VOS_IS_STATUS_SUCCESS(status))
6141 {
6142 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006143 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006144 }
6145 }
6146 else
6147 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006148 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006149 }
6150 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6151
6152 if (eHAL_STATUS_FAILURE ==
6153 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6154 0, NULL, eANI_BOOLEAN_FALSE))
6155 {
6156 hddLog(LOGE,
6157 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006158 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006159 }
6160
6161 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6162 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6163 eANI_BOOLEAN_FALSE) )
6164 {
6165 hddLog(LOGE,
6166 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6167 }
6168
6169 // Reset WNI_CFG_PROBE_RSP Flags
6170 wlan_hdd_reset_prob_rspies(pAdapter);
6171 kfree(pAdapter->sessionCtx.ap.beacon);
6172 pAdapter->sessionCtx.ap.beacon = NULL;
6173 }
6174 mutex_unlock(&pHddCtx->sap_lock);
6175 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006176
Jeff Johnson295189b2012-06-20 16:38:30 -07006177 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006178#ifdef WLAN_OPEN_SOURCE
6179 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6180#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006182
Jeff Johnson295189b2012-06-20 16:38:30 -07006183 default:
6184 break;
6185 }
6186
6187 EXIT();
6188 return VOS_STATUS_SUCCESS;
6189}
6190
6191VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6192{
6193 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6194 VOS_STATUS status;
6195 hdd_adapter_t *pAdapter;
6196
6197 ENTER();
6198
6199 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6200
6201 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6202 {
6203 pAdapter = pAdapterNode->pAdapter;
6204 netif_tx_disable(pAdapter->dev);
6205 netif_carrier_off(pAdapter->dev);
6206
6207 hdd_stop_adapter( pHddCtx, pAdapter );
6208
6209 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6210 pAdapterNode = pNext;
6211 }
6212
6213 EXIT();
6214
6215 return VOS_STATUS_SUCCESS;
6216}
6217
6218VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6219{
6220 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6221 VOS_STATUS status;
6222 hdd_adapter_t *pAdapter;
6223
6224 ENTER();
6225
6226 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6227
6228 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6229 {
6230 pAdapter = pAdapterNode->pAdapter;
6231 netif_tx_disable(pAdapter->dev);
6232 netif_carrier_off(pAdapter->dev);
6233
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006234 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6235
Jeff Johnson295189b2012-06-20 16:38:30 -07006236 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306237 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6238 {
6239 hdd_wmm_adapter_close( pAdapter );
6240 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6241 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006242
6243 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6244 pAdapterNode = pNext;
6245 }
6246
6247 EXIT();
6248
6249 return VOS_STATUS_SUCCESS;
6250}
6251
6252VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6253{
6254 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6255 VOS_STATUS status;
6256 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306257 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006258
6259 ENTER();
6260
6261 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6262
6263 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6264 {
6265 pAdapter = pAdapterNode->pAdapter;
6266
6267 switch(pAdapter->device_mode)
6268 {
6269 case WLAN_HDD_INFRA_STATION:
6270 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006271 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306272
6273 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6274
Jeff Johnson295189b2012-06-20 16:38:30 -07006275 hdd_init_station_mode(pAdapter);
6276 /* Open the gates for HDD to receive Wext commands */
6277 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006278 pHddCtx->scan_info.mScanPending = FALSE;
6279 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006280
6281 //Trigger the initial scan
6282 hdd_wlan_initial_scan(pAdapter);
6283
6284 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306285 if (eConnectionState_Associated == connState ||
6286 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006287 {
6288 union iwreq_data wrqu;
6289 memset(&wrqu, '\0', sizeof(wrqu));
6290 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6291 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6292 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006293 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006294
Jeff Johnson295189b2012-06-20 16:38:30 -07006295 /* indicate disconnected event to nl80211 */
6296 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6297 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006298 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306299 else if (eConnectionState_Connecting == connState)
6300 {
6301 /*
6302 * Indicate connect failure to supplicant if we were in the
6303 * process of connecting
6304 */
6305 cfg80211_connect_result(pAdapter->dev, NULL,
6306 NULL, 0, NULL, 0,
6307 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6308 GFP_KERNEL);
6309 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006310 break;
6311
6312 case WLAN_HDD_SOFTAP:
6313 /* softAP can handle SSR */
6314 break;
6315
6316 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006317 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006318 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006319 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006320 break;
6321
6322 case WLAN_HDD_MONITOR:
6323 /* monitor interface start */
6324 break;
6325 default:
6326 break;
6327 }
6328
6329 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6330 pAdapterNode = pNext;
6331 }
6332
6333 EXIT();
6334
6335 return VOS_STATUS_SUCCESS;
6336}
6337
6338VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6339{
6340 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6341 hdd_adapter_t *pAdapter;
6342 VOS_STATUS status;
6343 v_U32_t roamId;
6344
6345 ENTER();
6346
6347 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6348
6349 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6350 {
6351 pAdapter = pAdapterNode->pAdapter;
6352
6353 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6354 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6355 {
6356 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6357 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6358
6359 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6360 init_completion(&pAdapter->disconnect_comp_var);
6361 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6362 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6363
6364 wait_for_completion_interruptible_timeout(
6365 &pAdapter->disconnect_comp_var,
6366 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6367
6368 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6369 pHddCtx->isAmpAllowed = VOS_FALSE;
6370 sme_RoamConnect(pHddCtx->hHal,
6371 pAdapter->sessionId, &(pWextState->roamProfile),
6372 &roamId);
6373 }
6374
6375 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6376 pAdapterNode = pNext;
6377 }
6378
6379 EXIT();
6380
6381 return VOS_STATUS_SUCCESS;
6382}
6383
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006384void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6385{
6386 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6387 VOS_STATUS status;
6388 hdd_adapter_t *pAdapter;
6389 hdd_station_ctx_t *pHddStaCtx;
6390 hdd_ap_ctx_t *pHddApCtx;
6391 hdd_hostapd_state_t * pHostapdState;
6392 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6393 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6394 const char *p2pMode = "DEV";
6395 const char *ccMode = "Standalone";
6396 int n;
6397
6398 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6399 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6400 {
6401 pAdapter = pAdapterNode->pAdapter;
6402 switch (pAdapter->device_mode) {
6403 case WLAN_HDD_INFRA_STATION:
6404 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6405 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6406 staChannel = pHddStaCtx->conn_info.operationChannel;
6407 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6408 }
6409 break;
6410 case WLAN_HDD_P2P_CLIENT:
6411 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6412 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6413 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6414 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6415 p2pMode = "CLI";
6416 }
6417 break;
6418 case WLAN_HDD_P2P_GO:
6419 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6420 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6421 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6422 p2pChannel = pHddApCtx->operatingChannel;
6423 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6424 }
6425 p2pMode = "GO";
6426 break;
6427 case WLAN_HDD_SOFTAP:
6428 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6429 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6430 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6431 apChannel = pHddApCtx->operatingChannel;
6432 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6433 }
6434 break;
6435 default:
6436 break;
6437 }
6438 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6439 pAdapterNode = pNext;
6440 }
6441 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6442 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6443 }
6444 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6445 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6446 if (p2pChannel > 0) {
6447 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6448 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6449 }
6450 if (apChannel > 0) {
6451 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6452 apChannel, MAC_ADDR_ARRAY(apBssid));
6453 }
6454
6455 if (p2pChannel > 0 && apChannel > 0) {
6456 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6457 }
6458}
6459
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006460bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006461{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006462 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006463}
6464
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006465/* Once SSR is disabled then it cannot be set. */
6466void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006467{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006468 if (HDD_SSR_DISABLED == isSsrRequired)
6469 return;
6470
Jeff Johnson295189b2012-06-20 16:38:30 -07006471 isSsrRequired = value;
6472}
6473
6474VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6475 hdd_adapter_list_node_t** ppAdapterNode)
6476{
6477 VOS_STATUS status;
6478 spin_lock(&pHddCtx->hddAdapters.lock);
6479 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6480 (hdd_list_node_t**) ppAdapterNode );
6481 spin_unlock(&pHddCtx->hddAdapters.lock);
6482 return status;
6483}
6484
6485VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6486 hdd_adapter_list_node_t* pAdapterNode,
6487 hdd_adapter_list_node_t** pNextAdapterNode)
6488{
6489 VOS_STATUS status;
6490 spin_lock(&pHddCtx->hddAdapters.lock);
6491 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6492 (hdd_list_node_t*) pAdapterNode,
6493 (hdd_list_node_t**)pNextAdapterNode );
6494
6495 spin_unlock(&pHddCtx->hddAdapters.lock);
6496 return status;
6497}
6498
6499VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6500 hdd_adapter_list_node_t* pAdapterNode)
6501{
6502 VOS_STATUS status;
6503 spin_lock(&pHddCtx->hddAdapters.lock);
6504 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6505 &pAdapterNode->node );
6506 spin_unlock(&pHddCtx->hddAdapters.lock);
6507 return status;
6508}
6509
6510VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6511 hdd_adapter_list_node_t** ppAdapterNode)
6512{
6513 VOS_STATUS status;
6514 spin_lock(&pHddCtx->hddAdapters.lock);
6515 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6516 (hdd_list_node_t**) ppAdapterNode );
6517 spin_unlock(&pHddCtx->hddAdapters.lock);
6518 return status;
6519}
6520
6521VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6522 hdd_adapter_list_node_t* pAdapterNode)
6523{
6524 VOS_STATUS status;
6525 spin_lock(&pHddCtx->hddAdapters.lock);
6526 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6527 (hdd_list_node_t*) pAdapterNode );
6528 spin_unlock(&pHddCtx->hddAdapters.lock);
6529 return status;
6530}
6531
6532VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6533 hdd_adapter_list_node_t* pAdapterNode)
6534{
6535 VOS_STATUS status;
6536 spin_lock(&pHddCtx->hddAdapters.lock);
6537 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6538 (hdd_list_node_t*) pAdapterNode );
6539 spin_unlock(&pHddCtx->hddAdapters.lock);
6540 return status;
6541}
6542
6543hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6544 tSirMacAddr macAddr )
6545{
6546 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6547 hdd_adapter_t *pAdapter;
6548 VOS_STATUS status;
6549
6550 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6551
6552 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6553 {
6554 pAdapter = pAdapterNode->pAdapter;
6555
6556 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6557 macAddr, sizeof(tSirMacAddr) ) )
6558 {
6559 return pAdapter;
6560 }
6561 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6562 pAdapterNode = pNext;
6563 }
6564
6565 return NULL;
6566
6567}
6568
6569hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6570{
6571 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6572 hdd_adapter_t *pAdapter;
6573 VOS_STATUS status;
6574
6575 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6576
6577 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6578 {
6579 pAdapter = pAdapterNode->pAdapter;
6580
6581 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6582 IFNAMSIZ ) )
6583 {
6584 return pAdapter;
6585 }
6586 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6587 pAdapterNode = pNext;
6588 }
6589
6590 return NULL;
6591
6592}
6593
6594hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6595{
6596 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6597 hdd_adapter_t *pAdapter;
6598 VOS_STATUS status;
6599
6600 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6601
6602 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6603 {
6604 pAdapter = pAdapterNode->pAdapter;
6605
6606 if( pAdapter && (mode == pAdapter->device_mode) )
6607 {
6608 return pAdapter;
6609 }
6610 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6611 pAdapterNode = pNext;
6612 }
6613
6614 return NULL;
6615
6616}
6617
6618//Remove this function later
6619hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6620{
6621 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6622 hdd_adapter_t *pAdapter;
6623 VOS_STATUS status;
6624
6625 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6626
6627 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6628 {
6629 pAdapter = pAdapterNode->pAdapter;
6630
6631 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6632 {
6633 return pAdapter;
6634 }
6635
6636 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6637 pAdapterNode = pNext;
6638 }
6639
6640 return NULL;
6641
6642}
6643
Jeff Johnson295189b2012-06-20 16:38:30 -07006644/**---------------------------------------------------------------------------
6645
6646 \brief hdd_set_monitor_tx_adapter() -
6647
6648 This API initializes the adapter to be used while transmitting on monitor
6649 adapter.
6650
6651 \param - pHddCtx - Pointer to the HDD context.
6652 pAdapter - Adapter that will used for TX. This can be NULL.
6653 \return - None.
6654 --------------------------------------------------------------------------*/
6655void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6656{
6657 hdd_adapter_t *pMonAdapter;
6658
6659 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6660
6661 if( NULL != pMonAdapter )
6662 {
6663 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6664 }
6665}
Jeff Johnson295189b2012-06-20 16:38:30 -07006666/**---------------------------------------------------------------------------
6667
6668 \brief hdd_select_queue() -
6669
6670 This API returns the operating channel of the requested device mode
6671
6672 \param - pHddCtx - Pointer to the HDD context.
6673 - mode - Device mode for which operating channel is required
6674 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6675 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6676 \return - channel number. "0" id the requested device is not found OR it is not connected.
6677 --------------------------------------------------------------------------*/
6678v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6679{
6680 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6681 VOS_STATUS status;
6682 hdd_adapter_t *pAdapter;
6683 v_U8_t operatingChannel = 0;
6684
6685 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6686
6687 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6688 {
6689 pAdapter = pAdapterNode->pAdapter;
6690
6691 if( mode == pAdapter->device_mode )
6692 {
6693 switch(pAdapter->device_mode)
6694 {
6695 case WLAN_HDD_INFRA_STATION:
6696 case WLAN_HDD_P2P_CLIENT:
6697 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6698 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6699 break;
6700 case WLAN_HDD_SOFTAP:
6701 case WLAN_HDD_P2P_GO:
6702 /*softap connection info */
6703 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6704 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6705 break;
6706 default:
6707 break;
6708 }
6709
6710 break; //Found the device of interest. break the loop
6711 }
6712
6713 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6714 pAdapterNode = pNext;
6715 }
6716 return operatingChannel;
6717}
6718
6719#ifdef WLAN_FEATURE_PACKET_FILTERING
6720/**---------------------------------------------------------------------------
6721
6722 \brief hdd_set_multicast_list() -
6723
6724 This used to set the multicast address list.
6725
6726 \param - dev - Pointer to the WLAN device.
6727 - skb - Pointer to OS packet (sk_buff).
6728 \return - success/fail
6729
6730 --------------------------------------------------------------------------*/
6731static void hdd_set_multicast_list(struct net_device *dev)
6732{
6733 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006734 int mc_count;
6735 int i = 0;
6736 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306737
6738 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006739 {
6740 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306741 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006742 return;
6743 }
6744
6745 if (dev->flags & IFF_ALLMULTI)
6746 {
6747 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006748 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306749 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006750 }
6751 else
6752 {
6753 mc_count = netdev_mc_count(dev);
6754 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006755 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006756 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6757 {
6758 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006759 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306760 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006761 return;
6762 }
6763
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306764 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006765
6766 netdev_for_each_mc_addr(ha, dev) {
6767 if (i == mc_count)
6768 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306769 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6770 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08006771 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006772 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306773 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006774 i++;
6775 }
6776 }
6777 return;
6778}
6779#endif
6780
6781/**---------------------------------------------------------------------------
6782
6783 \brief hdd_select_queue() -
6784
6785 This function is registered with the Linux OS for network
6786 core to decide which queue to use first.
6787
6788 \param - dev - Pointer to the WLAN device.
6789 - skb - Pointer to OS packet (sk_buff).
6790 \return - ac, Queue Index/access category corresponding to UP in IP header
6791
6792 --------------------------------------------------------------------------*/
6793v_U16_t hdd_select_queue(struct net_device *dev,
6794 struct sk_buff *skb)
6795{
6796 return hdd_wmm_select_queue(dev, skb);
6797}
6798
6799
6800/**---------------------------------------------------------------------------
6801
6802 \brief hdd_wlan_initial_scan() -
6803
6804 This function triggers the initial scan
6805
6806 \param - pAdapter - Pointer to the HDD adapter.
6807
6808 --------------------------------------------------------------------------*/
6809void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6810{
6811 tCsrScanRequest scanReq;
6812 tCsrChannelInfo channelInfo;
6813 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006814 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006815 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6816
6817 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6818 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6819 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6820
6821 if(sme_Is11dSupported(pHddCtx->hHal))
6822 {
6823 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6824 if ( HAL_STATUS_SUCCESS( halStatus ) )
6825 {
6826 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6827 if( !scanReq.ChannelInfo.ChannelList )
6828 {
6829 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6830 vos_mem_free(channelInfo.ChannelList);
6831 return;
6832 }
6833 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6834 channelInfo.numOfChannels);
6835 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6836 vos_mem_free(channelInfo.ChannelList);
6837 }
6838
6839 scanReq.scanType = eSIR_PASSIVE_SCAN;
6840 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6841 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6842 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6843 }
6844 else
6845 {
6846 scanReq.scanType = eSIR_ACTIVE_SCAN;
6847 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6848 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6849 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6850 }
6851
6852 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6853 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6854 {
6855 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6856 __func__, halStatus );
6857 }
6858
6859 if(sme_Is11dSupported(pHddCtx->hHal))
6860 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6861}
6862
6863struct fullPowerContext
6864{
6865 struct completion completion;
6866 unsigned int magic;
6867};
6868#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6869
6870/**---------------------------------------------------------------------------
6871
6872 \brief hdd_full_power_callback() - HDD full power callback function
6873
6874 This is the function invoked by SME to inform the result of a full power
6875 request issued by HDD
6876
6877 \param - callbackcontext - Pointer to cookie
6878 \param - status - result of request
6879
6880 \return - None
6881
6882 --------------------------------------------------------------------------*/
6883static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6884{
6885 struct fullPowerContext *pContext = callbackContext;
6886
6887 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306888 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006889
6890 if (NULL == callbackContext)
6891 {
6892 hddLog(VOS_TRACE_LEVEL_ERROR,
6893 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006894 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006895 return;
6896 }
6897
6898 /* there is a race condition that exists between this callback function
6899 and the caller since the caller could time out either before or
6900 while this code is executing. we'll assume the timeout hasn't
6901 occurred, but we'll verify that right before we save our work */
6902
6903 if (POWER_CONTEXT_MAGIC != pContext->magic)
6904 {
6905 /* the caller presumably timed out so there is nothing we can do */
6906 hddLog(VOS_TRACE_LEVEL_WARN,
6907 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006908 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006909 return;
6910 }
6911
6912 /* the race is on. caller could have timed out immediately after
6913 we verified the magic, but if so, caller will wait a short time
6914 for us to notify the caller, so the context will stay valid */
6915 complete(&pContext->completion);
6916}
6917
6918/**---------------------------------------------------------------------------
6919
6920 \brief hdd_wlan_exit() - HDD WLAN exit function
6921
6922 This is the driver exit point (invoked during rmmod)
6923
6924 \param - pHddCtx - Pointer to the HDD Context
6925
6926 \return - None
6927
6928 --------------------------------------------------------------------------*/
6929void hdd_wlan_exit(hdd_context_t *pHddCtx)
6930{
6931 eHalStatus halStatus;
6932 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6933 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306934 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006935 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006936 struct fullPowerContext powerContext;
6937 long lrc;
6938
6939 ENTER();
6940
Jeff Johnson88ba7742013-02-27 14:36:02 -08006941 if (VOS_FTM_MODE != hdd_get_conparam())
6942 {
6943 // Unloading, restart logic is no more required.
6944 wlan_hdd_restart_deinit(pHddCtx);
6945 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006946
Jeff Johnson295189b2012-06-20 16:38:30 -07006947 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006948 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006949 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006950 {
6951 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6952 WLAN_HDD_INFRA_STATION);
6953 if (pAdapter == NULL)
6954 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6955
6956 if (pAdapter != NULL)
6957 {
6958 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6959 hdd_UnregisterWext(pAdapter->dev);
6960 }
6961 }
6962 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006963
Jeff Johnson295189b2012-06-20 16:38:30 -07006964 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006965 {
6966 wlan_hdd_ftm_close(pHddCtx);
6967 goto free_hdd_ctx;
6968 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006969 //Stop the Interface TX queue.
6970 //netif_tx_disable(pWlanDev);
6971 //netif_carrier_off(pWlanDev);
6972
Jeff Johnson295189b2012-06-20 16:38:30 -07006973 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6974 {
6975 pAdapter = hdd_get_adapter(pHddCtx,
6976 WLAN_HDD_SOFTAP);
6977 }
6978 else
6979 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006980 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006981 {
6982 pAdapter = hdd_get_adapter(pHddCtx,
6983 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006984 if (pAdapter == NULL)
6985 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006986 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006987 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006988 /* DeRegister with platform driver as client for Suspend/Resume */
6989 vosStatus = hddDeregisterPmOps(pHddCtx);
6990 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6991 {
6992 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6993 VOS_ASSERT(0);
6994 }
6995
6996 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
6997 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6998 {
6999 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7000 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007001
7002 // Cancel any outstanding scan requests. We are about to close all
7003 // of our adapters, but an adapter structure is what SME passes back
7004 // to our callback function. Hence if there are any outstanding scan
7005 // requests then there is a race condition between when the adapter
7006 // is closed and when the callback is invoked. We try to resolve that
7007 // race condition here by canceling any outstanding scans before we
7008 // close the adapters.
7009 // Note that the scans may be cancelled in an asynchronous manner, so
7010 // ideally there needs to be some kind of synchronization. Rather than
7011 // introduce a new synchronization here, we will utilize the fact that
7012 // we are about to Request Full Power, and since that is synchronized,
7013 // the expectation is that by the time Request Full Power has completed,
7014 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007015 if (NULL != pAdapter)
7016 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7017 else
7018 hddLog(VOS_TRACE_LEVEL_ERROR,
7019 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007020
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007021 //Stop the traffic monitor timer
7022 if ( VOS_TIMER_STATE_RUNNING ==
7023 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7024 {
7025 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7026 }
7027
7028 // Destroy the traffic monitor timer
7029 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7030 &pHddCtx->tx_rx_trafficTmr)))
7031 {
7032 hddLog(VOS_TRACE_LEVEL_ERROR,
7033 "%s: Cannot deallocate Traffic monitor timer", __func__);
7034 }
7035
Jeff Johnson295189b2012-06-20 16:38:30 -07007036 //Disable IMPS/BMPS as we do not want the device to enter any power
7037 //save mode during shutdown
7038 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7039 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7040 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7041
7042 //Ensure that device is in full power as we will touch H/W during vos_Stop
7043 init_completion(&powerContext.completion);
7044 powerContext.magic = POWER_CONTEXT_MAGIC;
7045
7046 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7047 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7048
7049 if (eHAL_STATUS_SUCCESS != halStatus)
7050 {
7051 if (eHAL_STATUS_PMC_PENDING == halStatus)
7052 {
7053 /* request was sent -- wait for the response */
7054 lrc = wait_for_completion_interruptible_timeout(
7055 &powerContext.completion,
7056 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
7057 /* either we have a response or we timed out
7058 either way, first invalidate our magic */
7059 powerContext.magic = 0;
7060 if (lrc <= 0)
7061 {
7062 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007063 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007064 /* there is a race condition such that the callback
7065 function could be executing at the same time we are. of
7066 primary concern is if the callback function had already
7067 verified the "magic" but hasn't yet set the completion
7068 variable. Since the completion variable is on our
7069 stack, we'll delay just a bit to make sure the data is
7070 still valid if that is the case */
7071 msleep(50);
7072 }
7073 }
7074 else
7075 {
7076 hddLog(VOS_TRACE_LEVEL_ERROR,
7077 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007078 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007079 VOS_ASSERT(0);
7080 /* continue -- need to clean up as much as possible */
7081 }
7082 }
7083
Yue Ma0d4891e2013-08-06 17:01:45 -07007084 hdd_debugfs_exit(pHddCtx);
7085
Jeff Johnson295189b2012-06-20 16:38:30 -07007086 // Unregister the Net Device Notifier
7087 unregister_netdevice_notifier(&hdd_netdev_notifier);
7088
Jeff Johnson295189b2012-06-20 16:38:30 -07007089 hdd_stop_all_adapters( pHddCtx );
7090
Jeff Johnson295189b2012-06-20 16:38:30 -07007091#ifdef WLAN_BTAMP_FEATURE
7092 vosStatus = WLANBAP_Stop(pVosContext);
7093 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7094 {
7095 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7096 "%s: Failed to stop BAP",__func__);
7097 }
7098#endif //WLAN_BTAMP_FEATURE
7099
7100 //Stop all the modules
7101 vosStatus = vos_stop( pVosContext );
7102 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7103 {
7104 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7105 "%s: Failed to stop VOSS",__func__);
7106 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7107 }
7108
Jeff Johnson295189b2012-06-20 16:38:30 -07007109 //Assert Deep sleep signal now to put Libra HW in lowest power state
7110 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7111 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7112
7113 //Vote off any PMIC voltage supplies
7114 vos_chipPowerDown(NULL, NULL, NULL);
7115
7116 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7117
Leo Chang59cdc7e2013-07-10 10:08:21 -07007118
Jeff Johnson295189b2012-06-20 16:38:30 -07007119 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007120 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007121
7122 //Close the scheduler before calling vos_close to make sure no thread is
7123 // scheduled after the each module close is called i.e after all the data
7124 // structures are freed.
7125 vosStatus = vos_sched_close( pVosContext );
7126 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7127 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7128 "%s: Failed to close VOSS Scheduler",__func__);
7129 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7130 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007131#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007132#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7133 /* Destroy the wake lock */
7134 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7135#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007136 /* Destroy the wake lock */
7137 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007138#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007139
7140 //Close VOSS
7141 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7142 vos_close(pVosContext);
7143
Jeff Johnson295189b2012-06-20 16:38:30 -07007144 //Close Watchdog
7145 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7146 vos_watchdog_close(pVosContext);
7147
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307148 //Clean up HDD Nlink Service
7149 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007150#ifdef WLAN_KD_READY_NOTIFIER
7151 nl_srv_exit(pHddCtx->ptt_pid);
7152#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307153 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007154#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307155
Jeff Johnson295189b2012-06-20 16:38:30 -07007156 /* Cancel the vote for XO Core ON.
7157 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7158 * exited at this point
7159 */
7160 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007161 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007162 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7163 {
7164 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7165 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007166 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007167 }
7168
7169 hdd_close_all_adapters( pHddCtx );
7170
7171
7172 //Free up dynamically allocated members inside HDD Adapter
7173 kfree(pHddCtx->cfg_ini);
7174 pHddCtx->cfg_ini= NULL;
7175
7176 /* free the power on lock from platform driver */
7177 if (free_riva_power_on_lock("wlan"))
7178 {
7179 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7180 __func__);
7181 }
7182
Jeff Johnson88ba7742013-02-27 14:36:02 -08007183free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007184 /* FTM mode, WIPHY did not registered
7185 If un-register here, system crash will happen */
7186 if (VOS_FTM_MODE != hdd_get_conparam())
7187 {
7188 wiphy_unregister(wiphy) ;
7189 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007190 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007191 if (hdd_is_ssr_required())
7192 {
7193 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007194 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007195 msleep(5000);
7196 }
7197 hdd_set_ssr_required (VOS_FALSE);
7198}
7199
7200
7201/**---------------------------------------------------------------------------
7202
7203 \brief hdd_update_config_from_nv() - Function to update the contents of
7204 the running configuration with parameters taken from NV storage
7205
7206 \param - pHddCtx - Pointer to the HDD global context
7207
7208 \return - VOS_STATUS_SUCCESS if successful
7209
7210 --------------------------------------------------------------------------*/
7211static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7212{
Jeff Johnson295189b2012-06-20 16:38:30 -07007213 v_BOOL_t itemIsValid = VOS_FALSE;
7214 VOS_STATUS status;
7215 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7216 v_U8_t macLoop;
7217
7218 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7219 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7220 if(status != VOS_STATUS_SUCCESS)
7221 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007222 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007223 return VOS_STATUS_E_FAILURE;
7224 }
7225
7226 if (itemIsValid == VOS_TRUE)
7227 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007228 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007229 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7230 VOS_MAX_CONCURRENCY_PERSONA);
7231 if(status != VOS_STATUS_SUCCESS)
7232 {
7233 /* Get MAC from NV fail, not update CFG info
7234 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007235 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007236 return VOS_STATUS_E_FAILURE;
7237 }
7238
7239 /* If first MAC is not valid, treat all others are not valid
7240 * Then all MACs will be got from ini file */
7241 if(vos_is_macaddr_zero(&macFromNV[0]))
7242 {
7243 /* MAC address in NV file is not configured yet */
7244 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7245 return VOS_STATUS_E_INVAL;
7246 }
7247
7248 /* Get MAC address from NV, update CFG info */
7249 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7250 {
7251 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7252 {
7253 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7254 /* This MAC is not valid, skip it
7255 * This MAC will be got from ini file */
7256 }
7257 else
7258 {
7259 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7260 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7261 VOS_MAC_ADDR_SIZE);
7262 }
7263 }
7264 }
7265 else
7266 {
7267 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7268 return VOS_STATUS_E_FAILURE;
7269 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007270
Jeff Johnson295189b2012-06-20 16:38:30 -07007271
7272 return VOS_STATUS_SUCCESS;
7273}
7274
7275/**---------------------------------------------------------------------------
7276
7277 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7278
7279 \param - pAdapter - Pointer to the HDD
7280
7281 \return - None
7282
7283 --------------------------------------------------------------------------*/
7284VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7285{
7286 eHalStatus halStatus;
7287 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307288 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007289
Jeff Johnson295189b2012-06-20 16:38:30 -07007290
7291 // Send ready indication to the HDD. This will kick off the MAC
7292 // into a 'running' state and should kick off an initial scan.
7293 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7294 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7295 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307296 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007297 "code %08d [x%08x]",__func__, halStatus, halStatus );
7298 return VOS_STATUS_E_FAILURE;
7299 }
7300
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307301 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007302 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7303 // And RIVA will crash
7304 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7305 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307306 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7307 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7308
7309
Jeff Johnson295189b2012-06-20 16:38:30 -07007310 return VOS_STATUS_SUCCESS;
7311}
7312
Jeff Johnson295189b2012-06-20 16:38:30 -07007313/* wake lock APIs for HDD */
7314void hdd_prevent_suspend(void)
7315{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007316#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007317 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007318#else
7319 wcnss_prevent_suspend();
7320#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007321}
7322
7323void hdd_allow_suspend(void)
7324{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007325#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007326 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007327#else
7328 wcnss_allow_suspend();
7329#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007330}
7331
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007332void hdd_allow_suspend_timeout(v_U32_t timeout)
7333{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007334#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007335 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007336#else
7337 /* Do nothing as there is no API in wcnss for timeout*/
7338#endif
7339}
7340
Jeff Johnson295189b2012-06-20 16:38:30 -07007341/**---------------------------------------------------------------------------
7342
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007343 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7344 information between Host and Riva
7345
7346 This function gets reported version of FW
7347 It also finds the version of Riva headers used to compile the host
7348 It compares the above two and prints a warning if they are different
7349 It gets the SW and HW version string
7350 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7351 indicating the features they support through a bitmap
7352
7353 \param - pHddCtx - Pointer to HDD context
7354
7355 \return - void
7356
7357 --------------------------------------------------------------------------*/
7358
7359void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7360{
7361
7362 tSirVersionType versionCompiled;
7363 tSirVersionType versionReported;
7364 tSirVersionString versionString;
7365 tANI_U8 fwFeatCapsMsgSupported = 0;
7366 VOS_STATUS vstatus;
7367
7368 /* retrieve and display WCNSS version information */
7369 do {
7370
7371 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7372 &versionCompiled);
7373 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7374 {
7375 hddLog(VOS_TRACE_LEVEL_FATAL,
7376 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007377 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007378 break;
7379 }
7380
7381 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7382 &versionReported);
7383 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7384 {
7385 hddLog(VOS_TRACE_LEVEL_FATAL,
7386 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007387 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007388 break;
7389 }
7390
7391 if ((versionCompiled.major != versionReported.major) ||
7392 (versionCompiled.minor != versionReported.minor) ||
7393 (versionCompiled.version != versionReported.version) ||
7394 (versionCompiled.revision != versionReported.revision))
7395 {
7396 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7397 "Host expected %u.%u.%u.%u\n",
7398 WLAN_MODULE_NAME,
7399 (int)versionReported.major,
7400 (int)versionReported.minor,
7401 (int)versionReported.version,
7402 (int)versionReported.revision,
7403 (int)versionCompiled.major,
7404 (int)versionCompiled.minor,
7405 (int)versionCompiled.version,
7406 (int)versionCompiled.revision);
7407 }
7408 else
7409 {
7410 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7411 WLAN_MODULE_NAME,
7412 (int)versionReported.major,
7413 (int)versionReported.minor,
7414 (int)versionReported.version,
7415 (int)versionReported.revision);
7416 }
7417
7418 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7419 versionString,
7420 sizeof(versionString));
7421 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7422 {
7423 hddLog(VOS_TRACE_LEVEL_FATAL,
7424 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007425 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007426 break;
7427 }
7428
7429 pr_info("%s: WCNSS software version %s\n",
7430 WLAN_MODULE_NAME, versionString);
7431
7432 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7433 versionString,
7434 sizeof(versionString));
7435 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7436 {
7437 hddLog(VOS_TRACE_LEVEL_FATAL,
7438 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007439 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007440 break;
7441 }
7442
7443 pr_info("%s: WCNSS hardware version %s\n",
7444 WLAN_MODULE_NAME, versionString);
7445
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007446 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7447 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007448 send the message only if it the riva is 1.1
7449 minor numbers for different riva branches:
7450 0 -> (1.0)Mainline Build
7451 1 -> (1.1)Mainline Build
7452 2->(1.04) Stability Build
7453 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007454 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007455 ((versionReported.minor>=1) && (versionReported.version>=1)))
7456 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7457 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007458
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007459 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007460 {
7461#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7462 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7463 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7464#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007465 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7466 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7467 {
7468 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7469 }
7470
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007471 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007472 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007473
7474 } while (0);
7475
7476}
7477
7478/**---------------------------------------------------------------------------
7479
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307480 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7481
7482 \param - pHddCtx - Pointer to the hdd context
7483
7484 \return - true if hardware supports 5GHz
7485
7486 --------------------------------------------------------------------------*/
7487static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7488{
7489 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7490 * then hardware support 5Ghz.
7491 */
7492 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7493 {
7494 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7495 return true;
7496 }
7497 else
7498 {
7499 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7500 __func__);
7501 return false;
7502 }
7503}
7504
7505
7506/**---------------------------------------------------------------------------
7507
Jeff Johnson295189b2012-06-20 16:38:30 -07007508 \brief hdd_wlan_startup() - HDD init function
7509
7510 This is the driver startup code executed once a WLAN device has been detected
7511
7512 \param - dev - Pointer to the underlying device
7513
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007514 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007515
7516 --------------------------------------------------------------------------*/
7517
7518int hdd_wlan_startup(struct device *dev )
7519{
7520 VOS_STATUS status;
7521 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007522 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007523 hdd_context_t *pHddCtx = NULL;
7524 v_CONTEXT_t pVosContext= NULL;
7525#ifdef WLAN_BTAMP_FEATURE
7526 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7527 WLANBAP_ConfigType btAmpConfig;
7528 hdd_config_t *pConfig;
7529#endif
7530 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007531 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007532
7533 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007534 /*
7535 * cfg80211: wiphy allocation
7536 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307537 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007538
7539 if(wiphy == NULL)
7540 {
7541 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007542 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007543 }
7544
7545 pHddCtx = wiphy_priv(wiphy);
7546
Jeff Johnson295189b2012-06-20 16:38:30 -07007547 //Initialize the adapter context to zeros.
7548 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7549
Jeff Johnson295189b2012-06-20 16:38:30 -07007550 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007551 hdd_prevent_suspend();
7552 pHddCtx->isLoadUnloadInProgress = TRUE;
7553
7554 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7555
7556 /*Get vos context here bcoz vos_open requires it*/
7557 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7558
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007559 if(pVosContext == NULL)
7560 {
7561 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7562 goto err_free_hdd_context;
7563 }
7564
Jeff Johnson295189b2012-06-20 16:38:30 -07007565 //Save the Global VOSS context in adapter context for future.
7566 pHddCtx->pvosContext = pVosContext;
7567
7568 //Save the adapter context in global context for future.
7569 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7570
Jeff Johnson295189b2012-06-20 16:38:30 -07007571 pHddCtx->parent_dev = dev;
7572
7573 init_completion(&pHddCtx->full_pwr_comp_var);
7574 init_completion(&pHddCtx->standby_comp_var);
7575 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007576 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007577 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307578 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007579
7580#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007581 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007582#else
7583 init_completion(&pHddCtx->driver_crda_req);
7584#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007585
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307586 spin_lock_init(&pHddCtx->schedScan_lock);
7587
Jeff Johnson295189b2012-06-20 16:38:30 -07007588 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7589
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307590#ifdef FEATURE_WLAN_TDLS
7591 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7592 * invoked by other instances also) to protect the concurrent
7593 * access for the Adapters by TDLS module.
7594 */
7595 mutex_init(&pHddCtx->tdls_lock);
7596#endif
7597
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307598 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007599 // Load all config first as TL config is needed during vos_open
7600 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7601 if(pHddCtx->cfg_ini == NULL)
7602 {
7603 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7604 goto err_free_hdd_context;
7605 }
7606
7607 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7608
7609 // Read and parse the qcom_cfg.ini file
7610 status = hdd_parse_config_ini( pHddCtx );
7611 if ( VOS_STATUS_SUCCESS != status )
7612 {
7613 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7614 __func__, WLAN_INI_FILE);
7615 goto err_config;
7616 }
Arif Hussaind5218912013-12-05 01:10:55 -08007617#ifdef MEMORY_DEBUG
7618 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
7619 vos_mem_init();
7620
7621 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
7622 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
7623#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007624
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307625 /* INI has been read, initialise the configuredMcastBcastFilter with
7626 * INI value as this will serve as the default value
7627 */
7628 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7629 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7630 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307631
7632 if (false == hdd_is_5g_supported(pHddCtx))
7633 {
7634 //5Ghz is not supported.
7635 if (1 != pHddCtx->cfg_ini->nBandCapability)
7636 {
7637 hddLog(VOS_TRACE_LEVEL_INFO,
7638 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7639 pHddCtx->cfg_ini->nBandCapability = 1;
7640 }
7641 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307642
7643 /* If SNR Monitoring is enabled, FW has to parse all beacons
7644 * for calcaluting and storing the average SNR, so set Nth beacon
7645 * filter to 1 to enable FW to parse all the beaocons
7646 */
7647 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7648 {
7649 /* The log level is deliberately set to WARN as overriding
7650 * nthBeaconFilter to 1 will increase power cosumption and this
7651 * might just prove helpful to detect the power issue.
7652 */
7653 hddLog(VOS_TRACE_LEVEL_WARN,
7654 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7655 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7656 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007657 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307658 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007659 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307660 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007661 {
7662 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307663 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7664 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007665 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007666
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007667 // Update VOS trace levels based upon the cfg.ini
7668 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7669 pHddCtx->cfg_ini->vosTraceEnableBAP);
7670 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7671 pHddCtx->cfg_ini->vosTraceEnableTL);
7672 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7673 pHddCtx->cfg_ini->vosTraceEnableWDI);
7674 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7675 pHddCtx->cfg_ini->vosTraceEnableHDD);
7676 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7677 pHddCtx->cfg_ini->vosTraceEnableSME);
7678 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7679 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307680 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7681 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007682 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7683 pHddCtx->cfg_ini->vosTraceEnableWDA);
7684 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7685 pHddCtx->cfg_ini->vosTraceEnableSYS);
7686 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7687 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007688 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7689 pHddCtx->cfg_ini->vosTraceEnableSAP);
7690 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7691 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007692
Jeff Johnson295189b2012-06-20 16:38:30 -07007693 // Update WDI trace levels based upon the cfg.ini
7694 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7695 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7696 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7697 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7698 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7699 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7700 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7701 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007702
Jeff Johnson88ba7742013-02-27 14:36:02 -08007703 if (VOS_FTM_MODE == hdd_get_conparam())
7704 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007705 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7706 {
7707 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7708 goto err_free_hdd_context;
7709 }
7710 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7711 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007712 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007713
Jeff Johnson88ba7742013-02-27 14:36:02 -08007714 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007715 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7716 {
7717 status = vos_watchdog_open(pVosContext,
7718 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7719
7720 if(!VOS_IS_STATUS_SUCCESS( status ))
7721 {
7722 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307723 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007724 }
7725 }
7726
7727 pHddCtx->isLogpInProgress = FALSE;
7728 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7729
Jeff Johnson295189b2012-06-20 16:38:30 -07007730 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7731 if(!VOS_IS_STATUS_SUCCESS(status))
7732 {
7733 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007734 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007735 }
7736
Amar Singhala49cbc52013-10-08 18:37:44 -07007737#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007738 /* initialize the NV module. This is required so that
7739 we can initialize the channel information in wiphy
7740 from the NV.bin data. The channel information in
7741 wiphy needs to be initialized before wiphy registration */
7742
7743 status = vos_nv_open();
7744 if (!VOS_IS_STATUS_SUCCESS(status))
7745 {
7746 /* NV module cannot be initialized */
7747 hddLog( VOS_TRACE_LEVEL_FATAL,
7748 "%s: vos_nv_open failed", __func__);
7749 goto err_clkvote;
7750 }
7751
7752 status = vos_init_wiphy_from_nv_bin();
7753 if (!VOS_IS_STATUS_SUCCESS(status))
7754 {
7755 /* NV module cannot be initialized */
7756 hddLog( VOS_TRACE_LEVEL_FATAL,
7757 "%s: vos_init_wiphy failed", __func__);
7758 goto err_vos_nv_close;
7759 }
7760
Amar Singhala49cbc52013-10-08 18:37:44 -07007761 /* registration of wiphy dev with cfg80211 */
7762 if (0 > wlan_hdd_cfg80211_register(wiphy))
7763 {
7764 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007765 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007766 }
7767#endif
7768
Jeff Johnson295189b2012-06-20 16:38:30 -07007769 status = vos_open( &pVosContext, 0);
7770 if ( !VOS_IS_STATUS_SUCCESS( status ))
7771 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007772 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007773 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007774 }
7775
Jeff Johnson295189b2012-06-20 16:38:30 -07007776 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7777
7778 if ( NULL == pHddCtx->hHal )
7779 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007780 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007781 goto err_vosclose;
7782 }
7783
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007784 status = vos_preStart( pHddCtx->pvosContext );
7785 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7786 {
7787 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7788 goto err_vosclose;
7789 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007790
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007791 /* Note that the vos_preStart() sequence triggers the cfg download.
7792 The cfg download must occur before we update the SME config
7793 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007794 status = hdd_set_sme_config( pHddCtx );
7795
7796 if ( VOS_STATUS_SUCCESS != status )
7797 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007798 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7799 goto err_vosclose;
7800 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007801
7802 //Initialize the WMM module
7803 status = hdd_wmm_init(pHddCtx);
7804 if (!VOS_IS_STATUS_SUCCESS(status))
7805 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007806 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007807 goto err_vosclose;
7808 }
7809
Jeff Johnson295189b2012-06-20 16:38:30 -07007810 /* In the integrated architecture we update the configuration from
7811 the INI file and from NV before vOSS has been started so that
7812 the final contents are available to send down to the cCPU */
7813
Arif Hussain66559122013-11-21 10:11:40 -08007814 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
7815 {
7816 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
7817 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
7818 __func__, enable_dfs_chan_scan);
7819 }
7820 if (0 == enable_11d || 1 == enable_11d)
7821 {
7822 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
7823 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
7824 __func__, enable_11d);
7825 }
7826
Jeff Johnson295189b2012-06-20 16:38:30 -07007827 // Apply the cfg.ini to cfg.dat
7828 if (FALSE == hdd_update_config_dat(pHddCtx))
7829 {
7830 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7831 goto err_vosclose;
7832 }
7833
7834 // Apply the NV to cfg.dat
7835 /* Prima Update MAC address only at here */
7836 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7837 {
7838#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7839 /* There was not a valid set of MAC Addresses in NV. See if the
7840 default addresses were modified by the cfg.ini settings. If so,
7841 we'll use them, but if not, we'll autogenerate a set of MAC
7842 addresses based upon the device serial number */
7843
7844 static const v_MACADDR_t default_address =
7845 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7846 unsigned int serialno;
7847 int i;
7848
7849 serialno = wcnss_get_serial_number();
7850 if ((0 != serialno) &&
7851 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7852 sizeof(default_address))))
7853 {
7854 /* cfg.ini has the default address, invoke autogen logic */
7855
7856 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7857 bytes of the serial number that can be used to generate
7858 the other 3 bytes of the MAC address. Mask off all but
7859 the lower 3 bytes (this will also make sure we don't
7860 overflow in the next step) */
7861 serialno &= 0x00FFFFFF;
7862
7863 /* we need a unique address for each session */
7864 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7865
7866 /* autogen all addresses */
7867 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7868 {
7869 /* start with the entire default address */
7870 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7871 /* then replace the lower 3 bytes */
7872 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7873 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7874 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7875
7876 serialno++;
7877 }
7878
7879 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7880 MAC_ADDRESS_STR,
7881 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7882 }
7883 else
7884#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7885 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007886 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007887 "%s: Invalid MAC address in NV, using MAC from ini file "
7888 MAC_ADDRESS_STR, __func__,
7889 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7890 }
7891 }
7892 {
7893 eHalStatus halStatus;
7894 // Set the MAC Address
7895 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7896 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7897 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7898 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7899
7900 if (!HAL_STATUS_SUCCESS( halStatus ))
7901 {
7902 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7903 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007904 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007905 }
7906 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007907
7908 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7909 Note: Firmware image will be read and downloaded inside vos_start API */
7910 status = vos_start( pHddCtx->pvosContext );
7911 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7912 {
7913 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7914 goto err_vosclose;
7915 }
7916
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007917 /* Exchange capability info between Host and FW and also get versioning info from FW */
7918 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007919
7920 status = hdd_post_voss_start_config( pHddCtx );
7921 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7922 {
7923 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7924 __func__);
7925 goto err_vosstop;
7926 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007927
7928#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307929 wlan_hdd_cfg80211_update_reg_info( wiphy );
7930
7931 /* registration of wiphy dev with cfg80211 */
7932 if (0 > wlan_hdd_cfg80211_register(wiphy))
7933 {
7934 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7935 goto err_vosstop;
7936 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007937#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007938
Jeff Johnson295189b2012-06-20 16:38:30 -07007939 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7940 {
7941 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7942 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7943 }
7944 else
7945 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007946 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7947 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7948 if (pAdapter != NULL)
7949 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307950 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007951 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307952 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7953 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7954 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007955
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307956 /* Generate the P2P Device Address. This consists of the device's
7957 * primary MAC address with the locally administered bit set.
7958 */
7959 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007960 }
7961 else
7962 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307963 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7964 if (p2p_dev_addr != NULL)
7965 {
7966 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7967 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7968 }
7969 else
7970 {
7971 hddLog(VOS_TRACE_LEVEL_FATAL,
7972 "%s: Failed to allocate mac_address for p2p_device",
7973 __func__);
7974 goto err_close_adapter;
7975 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007976 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007977
7978 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7979 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7980 if ( NULL == pP2pAdapter )
7981 {
7982 hddLog(VOS_TRACE_LEVEL_FATAL,
7983 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007984 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007985 goto err_close_adapter;
7986 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007987 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007988 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007989
7990 if( pAdapter == NULL )
7991 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007992 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7993 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07007994 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007995
Arif Hussain66559122013-11-21 10:11:40 -08007996 if (country_code)
7997 {
7998 eHalStatus ret;
7999 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8000#ifndef CONFIG_ENABLE_LINUX_REG
8001 hdd_checkandupdate_phymode(pAdapter, country_code);
8002#endif
8003 ret = sme_ChangeCountryCode(pHddCtx->hHal, NULL,
8004 country_code,
8005 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308006 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008007 if (eHAL_STATUS_SUCCESS == ret)
8008 {
8009 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8010 "%s: SME Change Country code from module param fail ret=%d",
8011 __func__, ret);
8012 }
8013 else
8014 {
8015 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module country code set to %c%c",
8016 __func__, country_code[0], country_code[1]);
8017 }
8018 }
8019
Jeff Johnson295189b2012-06-20 16:38:30 -07008020#ifdef WLAN_BTAMP_FEATURE
8021 vStatus = WLANBAP_Open(pVosContext);
8022 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8023 {
8024 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8025 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008026 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008027 }
8028
8029 vStatus = BSL_Init(pVosContext);
8030 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8031 {
8032 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8033 "%s: Failed to Init BSL",__func__);
8034 goto err_bap_close;
8035 }
8036 vStatus = WLANBAP_Start(pVosContext);
8037 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8038 {
8039 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8040 "%s: Failed to start TL",__func__);
8041 goto err_bap_close;
8042 }
8043
8044 pConfig = pHddCtx->cfg_ini;
8045 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8046 status = WLANBAP_SetConfig(&btAmpConfig);
8047
8048#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008049
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008050#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8051 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8052 {
8053 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8054 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8055 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8056 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8057 }
8058#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008059#ifdef FEATURE_WLAN_SCAN_PNO
8060 /*SME must send channel update configuration to RIVA*/
8061 sme_UpdateChannelConfig(pHddCtx->hHal);
8062#endif
8063
Jeff Johnson295189b2012-06-20 16:38:30 -07008064 /* Register with platform driver as client for Suspend/Resume */
8065 status = hddRegisterPmOps(pHddCtx);
8066 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8067 {
8068 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8069#ifdef WLAN_BTAMP_FEATURE
8070 goto err_bap_stop;
8071#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008072 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008073#endif //WLAN_BTAMP_FEATURE
8074 }
8075
Yue Ma0d4891e2013-08-06 17:01:45 -07008076 /* Open debugfs interface */
8077 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8078 {
8079 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8080 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008081 }
8082
Jeff Johnson295189b2012-06-20 16:38:30 -07008083 /* Register TM level change handler function to the platform */
8084 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8085 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8086 {
8087 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8088 goto err_unregister_pmops;
8089 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008090
8091 /* register for riva power on lock to platform driver */
8092 if (req_riva_power_on_lock("wlan"))
8093 {
8094 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8095 __func__);
8096 goto err_unregister_pmops;
8097 }
8098
Jeff Johnson295189b2012-06-20 16:38:30 -07008099 // register net device notifier for device change notification
8100 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8101
8102 if(ret < 0)
8103 {
8104 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8105 goto err_free_power_on_lock;
8106 }
8107
8108 //Initialize the nlink service
8109 if(nl_srv_init() != 0)
8110 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308111 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008112 goto err_reg_netdev;
8113 }
8114
Leo Chang4ce1cc52013-10-21 18:27:15 -07008115#ifdef WLAN_KD_READY_NOTIFIER
8116 pHddCtx->kd_nl_init = 1;
8117#endif /* WLAN_KD_READY_NOTIFIER */
8118
Jeff Johnson295189b2012-06-20 16:38:30 -07008119 //Initialize the BTC service
8120 if(btc_activate_service(pHddCtx) != 0)
8121 {
8122 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8123 goto err_nl_srv;
8124 }
8125
8126#ifdef PTT_SOCK_SVC_ENABLE
8127 //Initialize the PTT service
8128 if(ptt_sock_activate_svc(pHddCtx) != 0)
8129 {
8130 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8131 goto err_nl_srv;
8132 }
8133#endif
8134
Jeff Johnson295189b2012-06-20 16:38:30 -07008135 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008136 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008137 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008138 /* Action frame registered in one adapter which will
8139 * applicable to all interfaces
8140 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008141 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008142 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008143
8144 mutex_init(&pHddCtx->sap_lock);
8145
8146 pHddCtx->isLoadUnloadInProgress = FALSE;
8147
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008148#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008149#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8150 /* Initialize the wake lcok */
8151 wake_lock_init(&pHddCtx->rx_wake_lock,
8152 WAKE_LOCK_SUSPEND,
8153 "qcom_rx_wakelock");
8154#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008155 /* Initialize the wake lcok */
8156 wake_lock_init(&pHddCtx->sap_wake_lock,
8157 WAKE_LOCK_SUSPEND,
8158 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008159#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008160
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008161 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8162 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008163
8164 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8165 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308166#ifndef CONFIG_ENABLE_LINUX_REG
8167 /*updating wiphy so that regulatory user hints can be processed*/
8168 if (wiphy)
8169 {
8170 regulatory_hint(wiphy, "00");
8171 }
8172#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008173 // Initialize the restart logic
8174 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308175
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008176 //Register the traffic monitor timer now
8177 if ( pHddCtx->cfg_ini->dynSplitscan)
8178 {
8179 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8180 VOS_TIMER_TYPE_SW,
8181 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8182 (void *)pHddCtx);
8183 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008184 goto success;
8185
8186err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008187#ifdef WLAN_KD_READY_NOTIFIER
8188 nl_srv_exit(pHddCtx->ptt_pid);
8189#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008190 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008191#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008192err_reg_netdev:
8193 unregister_netdevice_notifier(&hdd_netdev_notifier);
8194
8195err_free_power_on_lock:
8196 free_riva_power_on_lock("wlan");
8197
8198err_unregister_pmops:
8199 hddDevTmUnregisterNotifyCallback(pHddCtx);
8200 hddDeregisterPmOps(pHddCtx);
8201
Yue Ma0d4891e2013-08-06 17:01:45 -07008202 hdd_debugfs_exit(pHddCtx);
8203
Jeff Johnson295189b2012-06-20 16:38:30 -07008204#ifdef WLAN_BTAMP_FEATURE
8205err_bap_stop:
8206 WLANBAP_Stop(pVosContext);
8207#endif
8208
8209#ifdef WLAN_BTAMP_FEATURE
8210err_bap_close:
8211 WLANBAP_Close(pVosContext);
8212#endif
8213
Jeff Johnson295189b2012-06-20 16:38:30 -07008214err_close_adapter:
8215 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008216
8217#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308218 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008219#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008220
8221err_vosstop:
8222 vos_stop(pVosContext);
8223
Amar Singhala49cbc52013-10-08 18:37:44 -07008224err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008225 status = vos_sched_close( pVosContext );
8226 if (!VOS_IS_STATUS_SUCCESS(status)) {
8227 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8228 "%s: Failed to close VOSS Scheduler", __func__);
8229 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8230 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008231 vos_close(pVosContext );
8232
8233err_wiphy_unregister:
8234
8235#ifdef CONFIG_ENABLE_LINUX_REG
8236 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008237
Amar Singhal0a402232013-10-11 20:57:16 -07008238err_vos_nv_close:
8239
8240 vos_nv_close();
8241
Jeff Johnson295189b2012-06-20 16:38:30 -07008242err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008243#endif
8244
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008245 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008246
8247err_wdclose:
8248 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8249 vos_watchdog_close(pVosContext);
8250
Jeff Johnson295189b2012-06-20 16:38:30 -07008251err_config:
8252 kfree(pHddCtx->cfg_ini);
8253 pHddCtx->cfg_ini= NULL;
8254
8255err_free_hdd_context:
8256 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008257 wiphy_free(wiphy) ;
8258 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008259 VOS_BUG(1);
8260
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008261 if (hdd_is_ssr_required())
8262 {
8263 /* WDI timeout had happened during load, so SSR is needed here */
8264 subsystem_restart("wcnss");
8265 msleep(5000);
8266 }
8267 hdd_set_ssr_required (VOS_FALSE);
8268
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008269 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008270
8271success:
8272 EXIT();
8273 return 0;
8274}
8275
8276/**---------------------------------------------------------------------------
8277
Jeff Johnson32d95a32012-09-10 13:15:23 -07008278 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008279
Jeff Johnson32d95a32012-09-10 13:15:23 -07008280 This is the driver entry point - called in different timeline depending
8281 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008282
8283 \param - None
8284
8285 \return - 0 for success, non zero for failure
8286
8287 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008288static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008289{
8290 VOS_STATUS status;
8291 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008292 struct device *dev = NULL;
8293 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008294#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8295 int max_retries = 0;
8296#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008297
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308298#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8299 vos_wconn_trace_init();
8300#endif
8301
Jeff Johnson295189b2012-06-20 16:38:30 -07008302 ENTER();
8303
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008304#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008305 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008306#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008307
8308 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8309 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8310
8311 //Power Up Libra WLAN card first if not already powered up
8312 status = vos_chipPowerUp(NULL,NULL,NULL);
8313 if (!VOS_IS_STATUS_SUCCESS(status))
8314 {
8315 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8316 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308317#ifdef WLAN_OPEN_SOURCE
8318 wake_lock_destroy(&wlan_wake_lock);
8319#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008320 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008321 }
8322
Jeff Johnson295189b2012-06-20 16:38:30 -07008323#ifdef ANI_BUS_TYPE_PCI
8324
8325 dev = wcnss_wlan_get_device();
8326
8327#endif // ANI_BUS_TYPE_PCI
8328
8329#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008330
8331#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8332 /* wait until WCNSS driver downloads NV */
8333 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8334 msleep(1000);
8335 }
8336 if (max_retries >= 5) {
8337 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308338#ifdef WLAN_OPEN_SOURCE
8339 wake_lock_destroy(&wlan_wake_lock);
8340#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008341 return -ENODEV;
8342 }
8343#endif
8344
Jeff Johnson295189b2012-06-20 16:38:30 -07008345 dev = wcnss_wlan_get_device();
8346#endif // ANI_BUS_TYPE_PLATFORM
8347
8348
8349 do {
8350 if (NULL == dev) {
8351 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8352 ret_status = -1;
8353 break;
8354 }
8355
Jeff Johnson295189b2012-06-20 16:38:30 -07008356#ifdef TIMER_MANAGER
8357 vos_timer_manager_init();
8358#endif
8359
8360 /* Preopen VOSS so that it is ready to start at least SAL */
8361 status = vos_preOpen(&pVosContext);
8362
8363 if (!VOS_IS_STATUS_SUCCESS(status))
8364 {
8365 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8366 ret_status = -1;
8367 break;
8368 }
8369
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008370#ifndef MODULE
8371 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8372 */
8373 hdd_set_conparam((v_UINT_t)con_mode);
8374#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008375
8376 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008377 if (hdd_wlan_startup(dev))
8378 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008379 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008380 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008381 vos_preClose( &pVosContext );
8382 ret_status = -1;
8383 break;
8384 }
8385
8386 /* Cancel the vote for XO Core ON
8387 * This is done here for safety purposes in case we re-initialize without turning
8388 * it OFF in any error scenario.
8389 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008390 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008391 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008392 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008393 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8394 {
8395 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008396 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008397 }
8398 } while (0);
8399
8400 if (0 != ret_status)
8401 {
8402 //Assert Deep sleep signal now to put Libra HW in lowest power state
8403 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8404 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8405
8406 //Vote off any PMIC voltage supplies
8407 vos_chipPowerDown(NULL, NULL, NULL);
8408#ifdef TIMER_MANAGER
8409 vos_timer_exit();
8410#endif
8411#ifdef MEMORY_DEBUG
8412 vos_mem_exit();
8413#endif
8414
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008415#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008416 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008417#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008418 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8419 }
8420 else
8421 {
8422 //Send WLAN UP indication to Nlink Service
8423 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8424
8425 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008426 }
8427
8428 EXIT();
8429
8430 return ret_status;
8431}
8432
Jeff Johnson32d95a32012-09-10 13:15:23 -07008433/**---------------------------------------------------------------------------
8434
8435 \brief hdd_module_init() - Init Function
8436
8437 This is the driver entry point (invoked when module is loaded using insmod)
8438
8439 \param - None
8440
8441 \return - 0 for success, non zero for failure
8442
8443 --------------------------------------------------------------------------*/
8444#ifdef MODULE
8445static int __init hdd_module_init ( void)
8446{
8447 return hdd_driver_init();
8448}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008449#else /* #ifdef MODULE */
8450static int __init hdd_module_init ( void)
8451{
8452 /* Driver initialization is delayed to fwpath_changed_handler */
8453 return 0;
8454}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008455#endif /* #ifdef MODULE */
8456
Jeff Johnson295189b2012-06-20 16:38:30 -07008457
8458/**---------------------------------------------------------------------------
8459
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008460 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008461
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008462 This is the driver exit point (invoked when module is unloaded using rmmod
8463 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008464
8465 \param - None
8466
8467 \return - None
8468
8469 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008470static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008471{
8472 hdd_context_t *pHddCtx = NULL;
8473 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008474 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008475
8476 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8477
8478 //Get the global vos context
8479 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8480
8481 if(!pVosContext)
8482 {
8483 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8484 goto done;
8485 }
8486
8487 //Get the HDD context.
8488 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8489
8490 if(!pHddCtx)
8491 {
8492 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8493 }
8494 else
8495 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008496 while(isWDresetInProgress()) {
8497 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8498 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008499 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008500
8501 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8502 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8503 "%s:SSR never completed, fatal error", __func__);
8504 VOS_BUG(0);
8505 }
8506 }
8507
Jeff Johnson295189b2012-06-20 16:38:30 -07008508
8509 pHddCtx->isLoadUnloadInProgress = TRUE;
8510 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8511
8512 //Do all the cleanup before deregistering the driver
8513 hdd_wlan_exit(pHddCtx);
8514 }
8515
Jeff Johnson295189b2012-06-20 16:38:30 -07008516 vos_preClose( &pVosContext );
8517
8518#ifdef TIMER_MANAGER
8519 vos_timer_exit();
8520#endif
8521#ifdef MEMORY_DEBUG
8522 vos_mem_exit();
8523#endif
8524
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308525#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8526 vos_wconn_trace_exit();
8527#endif
8528
Jeff Johnson295189b2012-06-20 16:38:30 -07008529done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008530#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008531 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008532#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008533 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8534}
8535
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008536/**---------------------------------------------------------------------------
8537
8538 \brief hdd_module_exit() - Exit function
8539
8540 This is the driver exit point (invoked when module is unloaded using rmmod)
8541
8542 \param - None
8543
8544 \return - None
8545
8546 --------------------------------------------------------------------------*/
8547static void __exit hdd_module_exit(void)
8548{
8549 hdd_driver_exit();
8550}
8551
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008552#ifdef MODULE
8553static int fwpath_changed_handler(const char *kmessage,
8554 struct kernel_param *kp)
8555{
Jeff Johnson76052702013-04-16 13:55:05 -07008556 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008557}
8558
8559static int con_mode_handler(const char *kmessage,
8560 struct kernel_param *kp)
8561{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008562 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008563}
8564#else /* #ifdef MODULE */
8565/**---------------------------------------------------------------------------
8566
Jeff Johnson76052702013-04-16 13:55:05 -07008567 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008568
Jeff Johnson76052702013-04-16 13:55:05 -07008569 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008570 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008571 - invoked when module parameter fwpath is modified from userspace to signal
8572 initializing the WLAN driver or when con_mode is modified from userspace
8573 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008574
8575 \return - 0 for success, non zero for failure
8576
8577 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008578static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008579{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008580 int ret_status;
8581
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008582 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008583 ret_status = hdd_driver_init();
8584 wlan_hdd_inited = ret_status ? 0 : 1;
8585 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008586 }
8587
8588 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008589
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008590 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008591
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
Jeff Johnson295189b2012-06-20 16:38:30 -07008597/**---------------------------------------------------------------------------
8598
Jeff Johnson76052702013-04-16 13:55:05 -07008599 \brief fwpath_changed_handler() - Handler Function
8600
8601 Handle changes to the fwpath parameter
8602
8603 \return - 0 for success, non zero for failure
8604
8605 --------------------------------------------------------------------------*/
8606static int fwpath_changed_handler(const char *kmessage,
8607 struct kernel_param *kp)
8608{
8609 int ret;
8610
8611 ret = param_set_copystring(kmessage, kp);
8612 if (0 == ret)
8613 ret = kickstart_driver();
8614 return ret;
8615}
8616
8617/**---------------------------------------------------------------------------
8618
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008619 \brief con_mode_handler() -
8620
8621 Handler function for module param con_mode when it is changed by userspace
8622 Dynamically linked - do nothing
8623 Statically linked - exit and init driver, as in rmmod and insmod
8624
Jeff Johnson76052702013-04-16 13:55:05 -07008625 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008626
Jeff Johnson76052702013-04-16 13:55:05 -07008627 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008628
8629 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008630static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008631{
Jeff Johnson76052702013-04-16 13:55:05 -07008632 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008633
Jeff Johnson76052702013-04-16 13:55:05 -07008634 ret = param_set_int(kmessage, kp);
8635 if (0 == ret)
8636 ret = kickstart_driver();
8637 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008638}
8639#endif /* #ifdef MODULE */
8640
8641/**---------------------------------------------------------------------------
8642
Jeff Johnson295189b2012-06-20 16:38:30 -07008643 \brief hdd_get_conparam() -
8644
8645 This is the driver exit point (invoked when module is unloaded using rmmod)
8646
8647 \param - None
8648
8649 \return - tVOS_CON_MODE
8650
8651 --------------------------------------------------------------------------*/
8652tVOS_CON_MODE hdd_get_conparam ( void )
8653{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008654#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008655 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008656#else
8657 return (tVOS_CON_MODE)curr_con_mode;
8658#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008659}
8660void hdd_set_conparam ( v_UINT_t newParam )
8661{
8662 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008663#ifndef MODULE
8664 curr_con_mode = con_mode;
8665#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008666}
8667/**---------------------------------------------------------------------------
8668
8669 \brief hdd_softap_sta_deauth() - function
8670
8671 This to take counter measure to handle deauth req from HDD
8672
8673 \param - pAdapter - Pointer to the HDD
8674
8675 \param - enable - boolean value
8676
8677 \return - None
8678
8679 --------------------------------------------------------------------------*/
8680
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008681VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008682{
Jeff Johnson295189b2012-06-20 16:38:30 -07008683 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008684 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008685
8686 ENTER();
8687
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008688 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8689 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008690
8691 //Ignore request to deauth bcmc station
8692 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008693 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008694
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008695 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008696
8697 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008698 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008699}
8700
8701/**---------------------------------------------------------------------------
8702
8703 \brief hdd_softap_sta_disassoc() - function
8704
8705 This to take counter measure to handle deauth req from HDD
8706
8707 \param - pAdapter - Pointer to the HDD
8708
8709 \param - enable - boolean value
8710
8711 \return - None
8712
8713 --------------------------------------------------------------------------*/
8714
8715void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8716{
8717 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8718
8719 ENTER();
8720
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308721 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008722
8723 //Ignore request to disassoc bcmc station
8724 if( pDestMacAddress[0] & 0x1 )
8725 return;
8726
8727 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8728}
8729
8730void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8731{
8732 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8733
8734 ENTER();
8735
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308736 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008737
8738 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8739}
8740
Jeff Johnson295189b2012-06-20 16:38:30 -07008741/**---------------------------------------------------------------------------
8742 *
8743 * \brief hdd_get__concurrency_mode() -
8744 *
8745 *
8746 * \param - None
8747 *
8748 * \return - CONCURRENCY MODE
8749 *
8750 * --------------------------------------------------------------------------*/
8751tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8752{
8753 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8754 hdd_context_t *pHddCtx;
8755
8756 if (NULL != pVosContext)
8757 {
8758 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8759 if (NULL != pHddCtx)
8760 {
8761 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8762 }
8763 }
8764
8765 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008766 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008767 return VOS_STA;
8768}
8769
8770/* Decide whether to allow/not the apps power collapse.
8771 * Allow apps power collapse if we are in connected state.
8772 * if not, allow only if we are in IMPS */
8773v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8774{
8775 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008776 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008777 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008778 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8779 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8780 hdd_adapter_t *pAdapter = NULL;
8781 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008782 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008783
Jeff Johnson295189b2012-06-20 16:38:30 -07008784 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8785 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008786
Yathish9f22e662012-12-10 14:21:35 -08008787 concurrent_state = hdd_get_concurrency_mode();
8788
8789#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8790 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8791 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8792 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8793 return TRUE;
8794#endif
8795
Jeff Johnson295189b2012-06-20 16:38:30 -07008796 /*loop through all adapters. TBD fix for Concurrency */
8797 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8798 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8799 {
8800 pAdapter = pAdapterNode->pAdapter;
8801 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8802 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8803 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008804 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008805 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008806 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008807 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8808 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008809 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008810 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008811 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8812 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008813 return FALSE;
8814 }
8815 }
8816 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8817 pAdapterNode = pNext;
8818 }
8819 return TRUE;
8820}
8821
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008822/* Decides whether to send suspend notification to Riva
8823 * if any adapter is in BMPS; then it is required */
8824v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8825{
8826 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8827 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8828
8829 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8830 {
8831 return TRUE;
8832 }
8833 return FALSE;
8834}
8835
Jeff Johnson295189b2012-06-20 16:38:30 -07008836void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8837{
8838 switch(mode)
8839 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008840 case VOS_STA_MODE:
8841 case VOS_P2P_CLIENT_MODE:
8842 case VOS_P2P_GO_MODE:
8843 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008844 pHddCtx->concurrency_mode |= (1 << mode);
8845 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008846 break;
8847 default:
8848 break;
8849
8850 }
8851 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8852 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8853}
8854
8855
8856void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8857{
8858 switch(mode)
8859 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008860 case VOS_STA_MODE:
8861 case VOS_P2P_CLIENT_MODE:
8862 case VOS_P2P_GO_MODE:
8863 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008864 pHddCtx->no_of_sessions[mode]--;
8865 if (!(pHddCtx->no_of_sessions[mode]))
8866 pHddCtx->concurrency_mode &= (~(1 << mode));
8867 break;
8868 default:
8869 break;
8870 }
8871 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8872 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8873}
8874
Jeff Johnsone7245742012-09-05 17:12:55 -07008875/**---------------------------------------------------------------------------
8876 *
8877 * \brief wlan_hdd_restart_init
8878 *
8879 * This function initalizes restart timer/flag. An internal function.
8880 *
8881 * \param - pHddCtx
8882 *
8883 * \return - None
8884 *
8885 * --------------------------------------------------------------------------*/
8886
8887static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8888{
8889 /* Initialize */
8890 pHddCtx->hdd_restart_retries = 0;
8891 atomic_set(&pHddCtx->isRestartInProgress, 0);
8892 vos_timer_init(&pHddCtx->hdd_restart_timer,
8893 VOS_TIMER_TYPE_SW,
8894 wlan_hdd_restart_timer_cb,
8895 pHddCtx);
8896}
8897/**---------------------------------------------------------------------------
8898 *
8899 * \brief wlan_hdd_restart_deinit
8900 *
8901 * This function cleans up the resources used. An internal function.
8902 *
8903 * \param - pHddCtx
8904 *
8905 * \return - None
8906 *
8907 * --------------------------------------------------------------------------*/
8908
8909static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8910{
8911
8912 VOS_STATUS vos_status;
8913 /* Block any further calls */
8914 atomic_set(&pHddCtx->isRestartInProgress, 1);
8915 /* Cleanup */
8916 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8917 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008918 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008919 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8920 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008921 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008922
8923}
8924
8925/**---------------------------------------------------------------------------
8926 *
8927 * \brief wlan_hdd_framework_restart
8928 *
8929 * This function uses a cfg80211 API to start a framework initiated WLAN
8930 * driver module unload/load.
8931 *
8932 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8933 *
8934 *
8935 * \param - pHddCtx
8936 *
8937 * \return - VOS_STATUS_SUCCESS: Success
8938 * VOS_STATUS_E_EMPTY: Adapter is Empty
8939 * VOS_STATUS_E_NOMEM: No memory
8940
8941 * --------------------------------------------------------------------------*/
8942
8943static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8944{
8945 VOS_STATUS status = VOS_STATUS_SUCCESS;
8946 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008947 int len = (sizeof (struct ieee80211_mgmt));
8948 struct ieee80211_mgmt *mgmt = NULL;
8949
8950 /* Prepare the DEAUTH managment frame with reason code */
8951 mgmt = kzalloc(len, GFP_KERNEL);
8952 if(mgmt == NULL)
8953 {
8954 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8955 "%s: memory allocation failed (%d bytes)", __func__, len);
8956 return VOS_STATUS_E_NOMEM;
8957 }
8958 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008959
8960 /* Iterate over all adapters/devices */
8961 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8962 do
8963 {
8964 if( (status == VOS_STATUS_SUCCESS) &&
8965 pAdapterNode &&
8966 pAdapterNode->pAdapter)
8967 {
8968 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8969 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8970 pAdapterNode->pAdapter->dev->name,
8971 pAdapterNode->pAdapter->device_mode,
8972 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008973 /*
8974 * CFG80211 event to restart the driver
8975 *
8976 * 'cfg80211_send_unprot_deauth' sends a
8977 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8978 * of SME(Linux Kernel) state machine.
8979 *
8980 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8981 * the driver.
8982 *
8983 */
8984
8985 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008986 }
8987 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8988 pAdapterNode = pNext;
8989 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8990
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008991
8992 /* Free the allocated management frame */
8993 kfree(mgmt);
8994
Jeff Johnsone7245742012-09-05 17:12:55 -07008995 /* Retry until we unload or reach max count */
8996 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
8997 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
8998
8999 return status;
9000
9001}
9002/**---------------------------------------------------------------------------
9003 *
9004 * \brief wlan_hdd_restart_timer_cb
9005 *
9006 * Restart timer callback. An internal function.
9007 *
9008 * \param - User data:
9009 *
9010 * \return - None
9011 *
9012 * --------------------------------------------------------------------------*/
9013
9014void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9015{
9016 hdd_context_t *pHddCtx = usrDataForCallback;
9017 wlan_hdd_framework_restart(pHddCtx);
9018 return;
9019
9020}
9021
9022
9023/**---------------------------------------------------------------------------
9024 *
9025 * \brief wlan_hdd_restart_driver
9026 *
9027 * This function sends an event to supplicant to restart the WLAN driver.
9028 *
9029 * This function is called from vos_wlanRestart.
9030 *
9031 * \param - pHddCtx
9032 *
9033 * \return - VOS_STATUS_SUCCESS: Success
9034 * VOS_STATUS_E_EMPTY: Adapter is Empty
9035 * VOS_STATUS_E_ALREADY: Request already in progress
9036
9037 * --------------------------------------------------------------------------*/
9038VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9039{
9040 VOS_STATUS status = VOS_STATUS_SUCCESS;
9041
9042 /* A tight check to make sure reentrancy */
9043 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9044 {
9045 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9046 "%s: WLAN restart is already in progress", __func__);
9047
9048 return VOS_STATUS_E_ALREADY;
9049 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009050 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009051#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009052 wcnss_reset_intr();
9053#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009054
Jeff Johnsone7245742012-09-05 17:12:55 -07009055 return status;
9056}
9057
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009058/*
9059 * API to find if there is any STA or P2P-Client is connected
9060 */
9061VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9062{
9063 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9064}
Jeff Johnsone7245742012-09-05 17:12:55 -07009065
Jeff Johnson295189b2012-06-20 16:38:30 -07009066//Register the module init/exit functions
9067module_init(hdd_module_init);
9068module_exit(hdd_module_exit);
9069
9070MODULE_LICENSE("Dual BSD/GPL");
9071MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9072MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9073
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009074module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9075 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009076
Jeff Johnson76052702013-04-16 13:55:05 -07009077module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009078 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009079
9080module_param(enable_dfs_chan_scan, int,
9081 S_IRUSR | S_IRGRP | S_IROTH);
9082
9083module_param(enable_11d, int,
9084 S_IRUSR | S_IRGRP | S_IROTH);
9085
9086module_param(country_code, charp,
9087 S_IRUSR | S_IRGRP | S_IROTH);