blob: 0721b286da063f67119ba33ce325719c913f979f [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*/
1130 if ((NULL != pAdapter) && (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
1131 {
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 Girigowda6cf0b822013-06-27 14:00:20 -07002446 tANI_U16 homeAwayTime = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002447
2448 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2449 value = value + 19;
2450 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002451 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002452 if (ret < 0)
2453 {
2454 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002455 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002456 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002457 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002458 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2459 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2460 ret = -EINVAL;
2461 goto exit;
2462 }
2463
2464 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2465 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2466 {
2467 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2468 "lfr mode value %d is out of range"
2469 " (Min: %d Max: %d)", maxTime,
2470 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2471 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2472 ret = -EINVAL;
2473 goto exit;
2474 }
2475
2476 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2477 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2478
2479 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002480
2481 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2482 * where RFS is the RF Switching time. It is twice RFS to consider the
2483 * time to go off channel and return to the home channel. */
2484 homeAwayTime = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2485 if (homeAwayTime < (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2486 {
2487 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002488 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)"
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002489 " Hence enforcing home away time to disable (0)",
2490 __func__, homeAwayTime, (maxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2491 homeAwayTime = 0;
2492 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2493 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_FALSE);
2494 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002495 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2496 }
2497 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2498 {
2499 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2500 char extra[32];
2501 tANI_U8 len = 0;
2502
2503 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002504 len = scnprintf(extra, sizeof(extra), "%s %d",
2505 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002506 if (copy_to_user(priv_data.buf, &extra, len + 1))
2507 {
2508 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2509 "%s: failed to copy data to user buffer", __func__);
2510 ret = -EFAULT;
2511 goto exit;
2512 }
2513 }
2514 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2515 {
2516 tANI_U8 *value = command;
2517 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2518
2519 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2520 value = value + 16;
2521 /* Convert the value from ascii to integer */
2522 ret = kstrtou16(value, 10, &val);
2523 if (ret < 0)
2524 {
2525 /* If the input value is greater than max value of datatype, then also
2526 kstrtou16 fails */
2527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2528 "%s: kstrtou16 failed range [%d - %d]", __func__,
2529 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2530 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2531 ret = -EINVAL;
2532 goto exit;
2533 }
2534
2535 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2536 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2537 {
2538 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2539 "scan home time value %d is out of range"
2540 " (Min: %d Max: %d)", val,
2541 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2542 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2543 ret = -EINVAL;
2544 goto exit;
2545 }
2546
2547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2548 "%s: Received Command to change scan home time = %d", __func__, val);
2549
2550 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2551 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2552 }
2553 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2554 {
2555 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2556 char extra[32];
2557 tANI_U8 len = 0;
2558
2559 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002560 len = scnprintf(extra, sizeof(extra), "%s %d",
2561 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002562 if (copy_to_user(priv_data.buf, &extra, len + 1))
2563 {
2564 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2565 "%s: failed to copy data to user buffer", __func__);
2566 ret = -EFAULT;
2567 goto exit;
2568 }
2569 }
2570 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2571 {
2572 tANI_U8 *value = command;
2573 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2574
2575 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2576 value = value + 17;
2577 /* Convert the value from ascii to integer */
2578 ret = kstrtou8(value, 10, &val);
2579 if (ret < 0)
2580 {
2581 /* If the input value is greater than max value of datatype, then also
2582 kstrtou8 fails */
2583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2584 "%s: kstrtou8 failed range [%d - %d]", __func__,
2585 CFG_ROAM_INTRA_BAND_MIN,
2586 CFG_ROAM_INTRA_BAND_MAX);
2587 ret = -EINVAL;
2588 goto exit;
2589 }
2590
2591 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2592 (val > CFG_ROAM_INTRA_BAND_MAX))
2593 {
2594 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2595 "intra band mode value %d is out of range"
2596 " (Min: %d Max: %d)", val,
2597 CFG_ROAM_INTRA_BAND_MIN,
2598 CFG_ROAM_INTRA_BAND_MAX);
2599 ret = -EINVAL;
2600 goto exit;
2601 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2603 "%s: Received Command to change intra band = %d", __func__, val);
2604
2605 pHddCtx->cfg_ini->nRoamIntraBand = val;
2606 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2607 }
2608 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2609 {
2610 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2611 char extra[32];
2612 tANI_U8 len = 0;
2613
2614 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002615 len = scnprintf(extra, sizeof(extra), "%s %d",
2616 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002617 if (copy_to_user(priv_data.buf, &extra, len + 1))
2618 {
2619 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2620 "%s: failed to copy data to user buffer", __func__);
2621 ret = -EFAULT;
2622 goto exit;
2623 }
2624 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002625 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2626 {
2627 tANI_U8 *value = command;
2628 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2629
2630 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2631 value = value + 15;
2632 /* Convert the value from ascii to integer */
2633 ret = kstrtou8(value, 10, &nProbes);
2634 if (ret < 0)
2635 {
2636 /* If the input value is greater than max value of datatype, then also
2637 kstrtou8 fails */
2638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2639 "%s: kstrtou8 failed range [%d - %d]", __func__,
2640 CFG_ROAM_SCAN_N_PROBES_MIN,
2641 CFG_ROAM_SCAN_N_PROBES_MAX);
2642 ret = -EINVAL;
2643 goto exit;
2644 }
2645
2646 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2647 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2648 {
2649 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2650 "NProbes value %d is out of range"
2651 " (Min: %d Max: %d)", nProbes,
2652 CFG_ROAM_SCAN_N_PROBES_MIN,
2653 CFG_ROAM_SCAN_N_PROBES_MAX);
2654 ret = -EINVAL;
2655 goto exit;
2656 }
2657
2658 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2659 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2660
2661 pHddCtx->cfg_ini->nProbes = nProbes;
2662 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2663 }
2664 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2665 {
2666 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2667 char extra[32];
2668 tANI_U8 len = 0;
2669
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002670 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002671 if (copy_to_user(priv_data.buf, &extra, len + 1))
2672 {
2673 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2674 "%s: failed to copy data to user buffer", __func__);
2675 ret = -EFAULT;
2676 goto exit;
2677 }
2678 }
2679 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2680 {
2681 tANI_U8 *value = command;
2682 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002683 tANI_U16 scanChannelMaxTime = 0;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002684
2685 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2686 /* input value is in units of msec */
2687 value = value + 20;
2688 /* Convert the value from ascii to integer */
2689 ret = kstrtou16(value, 10, &homeAwayTime);
2690 if (ret < 0)
2691 {
2692 /* If the input value is greater than max value of datatype, then also
2693 kstrtou8 fails */
2694 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2695 "%s: kstrtou8 failed range [%d - %d]", __func__,
2696 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2697 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2698 ret = -EINVAL;
2699 goto exit;
2700 }
2701
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002702 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2703 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2704 {
2705 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2706 "homeAwayTime value %d is out of range"
2707 " (Min: %d Max: %d)", homeAwayTime,
2708 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2709 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2710 ret = -EINVAL;
2711 goto exit;
2712 }
2713
2714 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2715 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
2716
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002717 /* Home Away Time should be atleast equal to (MaxDwell time + (2*RFS)),
2718 * where RFS is the RF Switching time. It is twice RFS to consider the
2719 * time to go off channel and return to the home channel. */
2720 scanChannelMaxTime = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2721 if (homeAwayTime < (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)))
2722 {
2723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002724 "%s: Invalid config, Home away time(%d) is less than (twice RF switching time + channel max time)(%d)"
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002725 " Hence enforcing home away time to disable (0)",
2726 __func__, homeAwayTime, (scanChannelMaxTime + (2 * HDD_ROAM_SCAN_CHANNEL_SWITCH_TIME)));
2727 homeAwayTime = 0;
2728 }
2729
2730 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2731 {
2732 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2733 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2734 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002735 }
2736 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2737 {
2738 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2739 char extra[32];
2740 tANI_U8 len = 0;
2741
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002742 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002743 if (copy_to_user(priv_data.buf, &extra, len + 1))
2744 {
2745 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2746 "%s: failed to copy data to user buffer", __func__);
2747 ret = -EFAULT;
2748 goto exit;
2749 }
2750 }
2751 else if (strncmp(command, "REASSOC", 7) == 0)
2752 {
2753 tANI_U8 *value = command;
2754 tANI_U8 channel = 0;
2755 tSirMacAddr targetApBssid;
2756 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002757#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2758 tCsrHandoffRequest handoffInfo;
2759#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002760 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002761 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2762
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002763 /* if not associated, no need to proceed with reassoc */
2764 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2765 {
2766 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2767 ret = -EINVAL;
2768 goto exit;
2769 }
2770
2771 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2772 if (eHAL_STATUS_SUCCESS != status)
2773 {
2774 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2775 "%s: Failed to parse reassoc command data", __func__);
2776 ret = -EINVAL;
2777 goto exit;
2778 }
2779
2780 /* if the target bssid is same as currently associated AP,
2781 then no need to proceed with reassoc */
2782 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2783 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2784 {
2785 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2786 ret = -EINVAL;
2787 goto exit;
2788 }
2789
2790 /* Check channel number is a valid channel number */
2791 if(VOS_STATUS_SUCCESS !=
2792 wlan_hdd_validate_operation_channel(pAdapter, channel))
2793 {
2794 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002795 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002796 return -EINVAL;
2797 }
2798
2799 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002800#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2801 handoffInfo.channel = channel;
2802 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2803 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2804#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002805 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002806 else if (strncmp(command, "SETWESMODE", 10) == 0)
2807 {
2808 tANI_U8 *value = command;
2809 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2810
2811 /* Move pointer to ahead of SETWESMODE<delimiter> */
2812 value = value + 11;
2813 /* Convert the value from ascii to integer */
2814 ret = kstrtou8(value, 10, &wesMode);
2815 if (ret < 0)
2816 {
2817 /* If the input value is greater than max value of datatype, then also
2818 kstrtou8 fails */
2819 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2820 "%s: kstrtou8 failed range [%d - %d]", __func__,
2821 CFG_ENABLE_WES_MODE_NAME_MIN,
2822 CFG_ENABLE_WES_MODE_NAME_MAX);
2823 ret = -EINVAL;
2824 goto exit;
2825 }
2826
2827 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2828 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2829 {
2830 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2831 "WES Mode value %d is out of range"
2832 " (Min: %d Max: %d)", wesMode,
2833 CFG_ENABLE_WES_MODE_NAME_MIN,
2834 CFG_ENABLE_WES_MODE_NAME_MAX);
2835 ret = -EINVAL;
2836 goto exit;
2837 }
2838 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2839 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2840
2841 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2842 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2843 }
2844 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2845 {
2846 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2847 char extra[32];
2848 tANI_U8 len = 0;
2849
Arif Hussain826d9412013-11-12 16:44:54 -08002850 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002851 if (copy_to_user(priv_data.buf, &extra, len + 1))
2852 {
2853 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2854 "%s: failed to copy data to user buffer", __func__);
2855 ret = -EFAULT;
2856 goto exit;
2857 }
2858 }
2859#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002860#ifdef FEATURE_WLAN_LFR
2861 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2862 {
2863 tANI_U8 *value = command;
2864 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2865
2866 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2867 value = value + 12;
2868 /* Convert the value from ascii to integer */
2869 ret = kstrtou8(value, 10, &lfrMode);
2870 if (ret < 0)
2871 {
2872 /* If the input value is greater than max value of datatype, then also
2873 kstrtou8 fails */
2874 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2875 "%s: kstrtou8 failed range [%d - %d]", __func__,
2876 CFG_LFR_FEATURE_ENABLED_MIN,
2877 CFG_LFR_FEATURE_ENABLED_MAX);
2878 ret = -EINVAL;
2879 goto exit;
2880 }
2881
2882 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2883 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2884 {
2885 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2886 "lfr mode value %d is out of range"
2887 " (Min: %d Max: %d)", lfrMode,
2888 CFG_LFR_FEATURE_ENABLED_MIN,
2889 CFG_LFR_FEATURE_ENABLED_MAX);
2890 ret = -EINVAL;
2891 goto exit;
2892 }
2893
2894 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2895 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2896
2897 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2898 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2899 }
2900#endif
2901#ifdef WLAN_FEATURE_VOWIFI_11R
2902 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2903 {
2904 tANI_U8 *value = command;
2905 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2906
2907 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2908 value = value + 18;
2909 /* Convert the value from ascii to integer */
2910 ret = kstrtou8(value, 10, &ft);
2911 if (ret < 0)
2912 {
2913 /* If the input value is greater than max value of datatype, then also
2914 kstrtou8 fails */
2915 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2916 "%s: kstrtou8 failed range [%d - %d]", __func__,
2917 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2918 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2919 ret = -EINVAL;
2920 goto exit;
2921 }
2922
2923 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2924 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2925 {
2926 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2927 "ft mode value %d is out of range"
2928 " (Min: %d Max: %d)", ft,
2929 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2930 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2931 ret = -EINVAL;
2932 goto exit;
2933 }
2934
2935 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2936 "%s: Received Command to change ft mode = %d", __func__, ft);
2937
2938 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2939 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2940 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302941
2942 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2943 {
2944 tANI_U8 *value = command;
2945 tSirMacAddr targetApBssid;
2946 tANI_U8 trigger = 0;
2947 eHalStatus status = eHAL_STATUS_SUCCESS;
2948 hdd_station_ctx_t *pHddStaCtx = NULL;
2949 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2950
2951 /* if not associated, no need to proceed with reassoc */
2952 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2953 {
2954 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2955 ret = -EINVAL;
2956 goto exit;
2957 }
2958
2959 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2960 if (eHAL_STATUS_SUCCESS != status)
2961 {
2962 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2963 "%s: Failed to parse reassoc command data", __func__);
2964 ret = -EINVAL;
2965 goto exit;
2966 }
2967
2968 /* if the target bssid is same as currently associated AP,
2969 then no need to proceed with reassoc */
2970 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2971 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2972 {
2973 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2974 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2975 __func__);
2976 ret = -EINVAL;
2977 goto exit;
2978 }
2979
2980 /* Proceed with scan/roam */
2981 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2982 &targetApBssid[0],
2983 (tSmeFastRoamTrigger)(trigger));
2984 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002985#endif
2986#ifdef FEATURE_WLAN_CCX
2987 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2988 {
2989 tANI_U8 *value = command;
2990 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2991
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002992 /* Check if the features OKC/CCX/11R are supported simultaneously,
2993 then this operation is not permitted (return FAILURE) */
2994 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2995 hdd_is_okc_mode_enabled(pHddCtx) &&
2996 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2997 {
2998 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2999 "%s: OKC/CCX/11R are supported simultaneously"
3000 " hence this operation is not permitted!", __func__);
3001 ret = -EPERM;
3002 goto exit;
3003 }
3004
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003005 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3006 value = value + 11;
3007 /* Convert the value from ascii to integer */
3008 ret = kstrtou8(value, 10, &ccxMode);
3009 if (ret < 0)
3010 {
3011 /* If the input value is greater than max value of datatype, then also
3012 kstrtou8 fails */
3013 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3014 "%s: kstrtou8 failed range [%d - %d]", __func__,
3015 CFG_CCX_FEATURE_ENABLED_MIN,
3016 CFG_CCX_FEATURE_ENABLED_MAX);
3017 ret = -EINVAL;
3018 goto exit;
3019 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003020 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
3021 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
3022 {
3023 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3024 "Ccx mode value %d is out of range"
3025 " (Min: %d Max: %d)", ccxMode,
3026 CFG_CCX_FEATURE_ENABLED_MIN,
3027 CFG_CCX_FEATURE_ENABLED_MAX);
3028 ret = -EINVAL;
3029 goto exit;
3030 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3032 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3033
3034 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3035 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3036 }
3037#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003038 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3039 {
3040 tANI_U8 *value = command;
3041 tANI_BOOLEAN roamScanControl = 0;
3042
3043 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3044 value = value + 19;
3045 /* Convert the value from ascii to integer */
3046 ret = kstrtou8(value, 10, &roamScanControl);
3047 if (ret < 0)
3048 {
3049 /* If the input value is greater than max value of datatype, then also
3050 kstrtou8 fails */
3051 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3052 "%s: kstrtou8 failed ", __func__);
3053 ret = -EINVAL;
3054 goto exit;
3055 }
3056
3057 if (0 != roamScanControl)
3058 {
3059 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3060 "roam scan control invalid value = %d",
3061 roamScanControl);
3062 ret = -EINVAL;
3063 goto exit;
3064 }
3065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3066 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3067
3068 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3069 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003070#ifdef FEATURE_WLAN_OKC
3071 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3072 {
3073 tANI_U8 *value = command;
3074 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3075
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003076 /* Check if the features OKC/CCX/11R are supported simultaneously,
3077 then this operation is not permitted (return FAILURE) */
3078 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3079 hdd_is_okc_mode_enabled(pHddCtx) &&
3080 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3081 {
3082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3083 "%s: OKC/CCX/11R are supported simultaneously"
3084 " hence this operation is not permitted!", __func__);
3085 ret = -EPERM;
3086 goto exit;
3087 }
3088
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003089 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3090 value = value + 11;
3091 /* Convert the value from ascii to integer */
3092 ret = kstrtou8(value, 10, &okcMode);
3093 if (ret < 0)
3094 {
3095 /* If the input value is greater than max value of datatype, then also
3096 kstrtou8 fails */
3097 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3098 "%s: kstrtou8 failed range [%d - %d]", __func__,
3099 CFG_OKC_FEATURE_ENABLED_MIN,
3100 CFG_OKC_FEATURE_ENABLED_MAX);
3101 ret = -EINVAL;
3102 goto exit;
3103 }
3104
3105 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3106 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3107 {
3108 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3109 "Okc mode value %d is out of range"
3110 " (Min: %d Max: %d)", okcMode,
3111 CFG_OKC_FEATURE_ENABLED_MIN,
3112 CFG_OKC_FEATURE_ENABLED_MAX);
3113 ret = -EINVAL;
3114 goto exit;
3115 }
3116
3117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3118 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3119
3120 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3121 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003122#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003123 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3124 {
3125 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3126 char extra[32];
3127 tANI_U8 len = 0;
3128
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003129 len = scnprintf(extra, sizeof(extra), "%s %d",
3130 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003131 if (copy_to_user(priv_data.buf, &extra, len + 1))
3132 {
3133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3134 "%s: failed to copy data to user buffer", __func__);
3135 ret = -EFAULT;
3136 goto exit;
3137 }
3138 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303139#ifdef WLAN_FEATURE_PACKET_FILTERING
3140 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3141 {
3142 tANI_U8 filterType = 0;
3143 tANI_U8 *value = command;
3144
3145 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3146 value = value + 22;
3147
3148 /* Convert the value from ascii to integer */
3149 ret = kstrtou8(value, 10, &filterType);
3150 if (ret < 0)
3151 {
3152 /* If the input value is greater than max value of datatype,
3153 * then also kstrtou8 fails
3154 */
3155 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3156 "%s: kstrtou8 failed range ", __func__);
3157 ret = -EINVAL;
3158 goto exit;
3159 }
3160
3161 if (filterType != 0 && filterType != 1)
3162 {
3163 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3164 "%s: Accepted Values are 0 and 1 ", __func__);
3165 ret = -EINVAL;
3166 goto exit;
3167 }
3168 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3169 pAdapter->sessionId);
3170 }
3171#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303172 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3173 {
3174 char *dhcpPhase;
3175 dhcpPhase = command + 12;
3176 if ('1' == *dhcpPhase)
3177 {
3178 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3179 pAdapter->macAddressCurrent.bytes);
3180 }
3181 else if ('2' == *dhcpPhase)
3182 {
3183 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3184 pAdapter->macAddressCurrent.bytes);
3185 }
3186 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003187 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3188 {
3189 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3190 }
3191 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3192 {
3193 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3194 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303195 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3196 {
3197 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3198 char extra[32];
3199 tANI_U8 len = 0;
3200
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003201 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303202 (int)pCfg->nActiveMaxChnTime);
3203 if (copy_to_user(priv_data.buf, &extra, len + 1))
3204 {
3205 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3206 "%s: failed to copy data to user buffer", __func__);
3207 ret = -EFAULT;
3208 goto exit;
3209 }
3210 ret = len;
3211 }
3212 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3213 {
3214 tANI_U8 *value = command;
3215 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3216 int val = 0, temp;
3217
3218 value = value + 13;
3219 temp = kstrtou32(value, 10, &val);
3220 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3221 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3222 {
3223 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3224 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3225 ret = -EFAULT;
3226 goto exit;
3227 }
3228 pCfg->nActiveMaxChnTime = val;
3229 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003230 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3231 {
3232 tANI_U8 filterType = 0;
3233 tANI_U8 *value;
3234 value = command + 9;
3235
3236 /* Convert the value from ascii to integer */
3237 ret = kstrtou8(value, 10, &filterType);
3238 if (ret < 0)
3239 {
3240 /* If the input value is greater than max value of datatype,
3241 * then also kstrtou8 fails
3242 */
3243 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3244 "%s: kstrtou8 failed range ", __func__);
3245 ret = -EINVAL;
3246 goto exit;
3247 }
3248 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3249 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3250 {
3251 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3252 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3253 " 2-Sink ", __func__);
3254 ret = -EINVAL;
3255 goto exit;
3256 }
3257 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3258 pHddCtx->drvr_miracast = filterType;
3259 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3260 }
Leo Chang614d2072013-08-22 14:59:44 -07003261 else if (strncmp(command, "SETMCRATE", 9) == 0)
3262 {
Leo Chang614d2072013-08-22 14:59:44 -07003263 tANI_U8 *value = command;
3264 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003265 tSirRateUpdateInd *rateUpdate;
3266 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003267
3268 /* Only valid for SAP mode */
3269 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3270 {
3271 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3272 "%s: SAP mode is not running", __func__);
3273 ret = -EFAULT;
3274 goto exit;
3275 }
3276
3277 /* Move pointer to ahead of SETMCRATE<delimiter> */
3278 /* input value is in units of hundred kbps */
3279 value = value + 10;
3280 /* Convert the value from ascii to integer, decimal base */
3281 ret = kstrtouint(value, 10, &targetRate);
3282
Leo Chang1f98cbd2013-10-17 15:03:52 -07003283 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3284 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003285 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003286 hddLog(VOS_TRACE_LEVEL_ERROR,
3287 "%s: SETMCRATE indication alloc fail", __func__);
3288 ret = -EFAULT;
3289 goto exit;
3290 }
3291 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3292
3293 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3294 "MC Target rate %d", targetRate);
3295 /* Ignore unicast */
3296 rateUpdate->ucastDataRate = -1;
3297 rateUpdate->mcastDataRate24GHz = targetRate;
3298 rateUpdate->mcastDataRate5GHz = targetRate;
3299 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3300 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3301 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3302 if (eHAL_STATUS_SUCCESS != status)
3303 {
3304 hddLog(VOS_TRACE_LEVEL_ERROR,
3305 "%s: SET_MC_RATE failed", __func__);
3306 vos_mem_free(rateUpdate);
3307 ret = -EFAULT;
3308 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003309 }
3310 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303311#ifdef FEATURE_WLAN_BATCH_SCAN
3312 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3313 {
3314 char extra[32];
3315 tANI_U8 len = 0;
3316 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3317
3318 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3319 {
3320 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3321 "%s: Batch scan feature is not supported by FW", __func__);
3322 ret = -EINVAL;
3323 goto exit;
3324 }
3325
3326 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3327 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3328 {
3329 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3330 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3331 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3332 " mode",
3333 pAdapter->device_mode);
3334 ret = -EINVAL;
3335 goto exit;
3336 }
3337
Arif Hussain826d9412013-11-12 16:44:54 -08003338 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
Rajeev79dbe4c2013-10-05 11:03:42 +05303339 version);
3340 if (copy_to_user(priv_data.buf, &extra, len + 1))
3341 {
3342 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3343 "%s: failed to copy data to user buffer", __func__);
3344 ret = -EFAULT;
3345 goto exit;
3346 }
3347 ret = HDD_BATCH_SCAN_VERSION;
3348 }
3349 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3350 {
3351 int status;
3352 tANI_U8 *value = (command + 16);
3353 eHalStatus halStatus;
3354 unsigned long rc;
3355 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3356 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3357
3358 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3359 {
3360 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3361 "%s: Batch scan feature is not supported by FW", __func__);
3362 ret = -EINVAL;
3363 goto exit;
3364 }
3365
Rajeev Kumar20140c12013-10-21 19:39:02 -07003366
Rajeev79dbe4c2013-10-05 11:03:42 +05303367 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3368 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3369 {
3370 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003371 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303372 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3373 pAdapter->device_mode);
3374 ret = -EINVAL;
3375 goto exit;
3376 }
3377
Rajeev Kumar20140c12013-10-21 19:39:02 -07003378
Rajeev79dbe4c2013-10-05 11:03:42 +05303379 status = hdd_parse_set_batchscan_command(value, pReq);
3380 if (status)
3381 {
3382 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003383 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303384 ret = -EINVAL;
3385 goto exit;
3386 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003387
3388
Rajeev79dbe4c2013-10-05 11:03:42 +05303389 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3390 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3391 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3392 pAdapter);
3393
3394 if ( eHAL_STATUS_SUCCESS == halStatus )
3395 {
3396 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3397 "sme_SetBatchScanReq returned success halStatus %d",
3398 halStatus);
3399 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3400 {
3401 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3402 rc = wait_for_completion_timeout(
3403 &pAdapter->hdd_set_batch_scan_req_var,
3404 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3405 if (0 == rc)
3406 {
3407 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3408 "%s: Timeout waiting for set batch scan to complete",
3409 __func__);
3410 ret = -EINVAL;
3411 goto exit;
3412 }
3413 }
3414 if ( !pRsp->nScansToBatch )
3415 {
3416 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3417 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003418 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303419 ret = -EINVAL;
3420 goto exit;
3421 }
3422 /*As per the Batch Scan Framework API we should return the MIN of
3423 either MSCAN or the max # of scans firmware can cache*/
3424 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3425
Rajeev Kumar20140c12013-10-21 19:39:02 -07003426 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3427
Rajeev79dbe4c2013-10-05 11:03:42 +05303428 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3429 "%s: request MSCAN %d response MSCAN %d ret %d",
3430 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3431 }
3432 else
3433 {
3434 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3435 "sme_SetBatchScanReq returned failure halStatus %d",
3436 halStatus);
3437 ret = -EINVAL;
3438 goto exit;
3439 }
3440 }
3441 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3442 {
3443 eHalStatus halStatus;
3444 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3445 pInd->param = 0;
3446
3447 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3448 {
3449 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3450 "%s: Batch scan feature is not supported by FW", __func__);
3451 ret = -EINVAL;
3452 goto exit;
3453 }
3454
Rajeev Kumar20140c12013-10-21 19:39:02 -07003455 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303456 {
3457 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003458 "Batch scan is not yet enabled batch scan state %d",
3459 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303460 ret = -EINVAL;
3461 goto exit;
3462 }
3463
Rajeev Kumar20140c12013-10-21 19:39:02 -07003464 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3465
Rajeev79dbe4c2013-10-05 11:03:42 +05303466 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3467 pAdapter->sessionId);
3468 if ( eHAL_STATUS_SUCCESS == halStatus )
3469 {
3470 ret = 0;
3471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3472 "sme_StopBatchScanInd returned success halStatus %d",
3473 halStatus);
3474 }
3475 else
3476 {
3477 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3478 "sme_StopBatchScanInd returned failure halStatus %d",
3479 halStatus);
3480 ret = -EINVAL;
3481 goto exit;
3482 }
3483 }
3484 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3485 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003486 tANI_U32 remain_len;
3487
Rajeev79dbe4c2013-10-05 11:03:42 +05303488 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3489 {
3490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3491 "%s: Batch scan feature is not supported by FW", __func__);
3492 ret = -EINVAL;
3493 goto exit;
3494 }
3495
Rajeev Kumar20140c12013-10-21 19:39:02 -07003496 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303497 {
3498 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003499 "Batch scan is not yet enabled could not return results"
3500 "Batch Scan state %d",
3501 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303502 ret = -EINVAL;
3503 goto exit;
3504 }
3505
3506 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003507 remain_len = priv_data.total_len - priv_data.used_len;
3508 if (remain_len < priv_data.total_len)
3509 {
3510 /*Clear previous batch scan response data if any*/
3511 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3512 }
3513 else
3514 {
3515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3516 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003517 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003518 priv_data.total_len, priv_data.used_len, remain_len);
3519 ret = -EINVAL;
3520 goto exit;
3521 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303522 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3523 }
3524#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003525#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3526 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3527 {
3528 tANI_U8 *value = command;
3529 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3530 tANI_U8 numChannels = 0;
3531 eHalStatus status = eHAL_STATUS_SUCCESS;
3532
3533 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3534 if (eHAL_STATUS_SUCCESS != status)
3535 {
3536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3537 "%s: Failed to parse channel list information", __func__);
3538 ret = -EINVAL;
3539 goto exit;
3540 }
3541
3542 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3543 {
3544 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3545 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3546 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3547 ret = -EINVAL;
3548 goto exit;
3549 }
3550 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3551 ChannelList,
3552 numChannels);
3553 if (eHAL_STATUS_SUCCESS != status)
3554 {
3555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3556 "%s: Failed to update channel list information", __func__);
3557 ret = -EINVAL;
3558 goto exit;
3559 }
3560 }
3561 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3562 {
3563 tANI_U8 *value = command;
3564 char extra[128] = {0};
3565 int len = 0;
3566 tANI_U8 tid = 0;
3567 hdd_station_ctx_t *pHddStaCtx = NULL;
3568 tAniTrafStrmMetrics tsmMetrics;
3569 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3570
3571 /* if not associated, return error */
3572 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3573 {
3574 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3575 ret = -EINVAL;
3576 goto exit;
3577 }
3578
3579 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3580 value = value + 12;
3581 /* Convert the value from ascii to integer */
3582 ret = kstrtou8(value, 10, &tid);
3583 if (ret < 0)
3584 {
3585 /* If the input value is greater than max value of datatype, then also
3586 kstrtou8 fails */
3587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3588 "%s: kstrtou8 failed range [%d - %d]", __func__,
3589 TID_MIN_VALUE,
3590 TID_MAX_VALUE);
3591 ret = -EINVAL;
3592 goto exit;
3593 }
3594
3595 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3596 {
3597 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3598 "tid value %d is out of range"
3599 " (Min: %d Max: %d)", tid,
3600 TID_MIN_VALUE,
3601 TID_MAX_VALUE);
3602 ret = -EINVAL;
3603 goto exit;
3604 }
3605
3606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3607 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3608
3609 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3610 {
3611 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3612 "%s: failed to get tsm stats", __func__);
3613 ret = -EFAULT;
3614 goto exit;
3615 }
3616
3617 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3618 "UplinkPktQueueDly(%d)\n"
3619 "UplinkPktQueueDlyHist[0](%d)\n"
3620 "UplinkPktQueueDlyHist[1](%d)\n"
3621 "UplinkPktQueueDlyHist[2](%d)\n"
3622 "UplinkPktQueueDlyHist[3](%d)\n"
3623 "UplinkPktTxDly(%lu)\n"
3624 "UplinkPktLoss(%d)\n"
3625 "UplinkPktCount(%d)\n"
3626 "RoamingCount(%d)\n"
3627 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3628 tsmMetrics.UplinkPktQueueDlyHist[0],
3629 tsmMetrics.UplinkPktQueueDlyHist[1],
3630 tsmMetrics.UplinkPktQueueDlyHist[2],
3631 tsmMetrics.UplinkPktQueueDlyHist[3],
3632 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3633 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3634
3635 /* Output TSM stats is of the format
3636 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3637 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003638 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003639 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3640 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3641 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3642 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3643 tsmMetrics.RoamingDly);
3644
3645 if (copy_to_user(priv_data.buf, &extra, len + 1))
3646 {
3647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3648 "%s: failed to copy data to user buffer", __func__);
3649 ret = -EFAULT;
3650 goto exit;
3651 }
3652 }
3653 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3654 {
3655 tANI_U8 *value = command;
3656 tANI_U8 *cckmIe = NULL;
3657 tANI_U8 cckmIeLen = 0;
3658 eHalStatus status = eHAL_STATUS_SUCCESS;
3659
3660 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3661 if (eHAL_STATUS_SUCCESS != status)
3662 {
3663 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3664 "%s: Failed to parse cckm ie data", __func__);
3665 ret = -EINVAL;
3666 goto exit;
3667 }
3668
3669 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3670 {
3671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3672 "%s: CCKM Ie input length is more than max[%d]", __func__,
3673 DOT11F_IE_RSN_MAX_LEN);
3674 if (NULL != cckmIe)
3675 {
3676 vos_mem_free(cckmIe);
3677 }
3678 ret = -EINVAL;
3679 goto exit;
3680 }
3681 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3682 if (NULL != cckmIe)
3683 {
3684 vos_mem_free(cckmIe);
3685 }
3686 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003687 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3688 {
3689 tANI_U8 *value = command;
3690 tCsrCcxBeaconReq ccxBcnReq;
3691 eHalStatus status = eHAL_STATUS_SUCCESS;
3692 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3693 if (eHAL_STATUS_SUCCESS != status)
3694 {
3695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3696 "%s: Failed to parse ccx beacon req", __func__);
3697 ret = -EINVAL;
3698 goto exit;
3699 }
3700
3701 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3702 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003703#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003704 else {
3705 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3706 __func__, command);
3707 }
3708
Jeff Johnson295189b2012-06-20 16:38:30 -07003709 }
3710exit:
3711 if (command)
3712 {
3713 kfree(command);
3714 }
3715 return ret;
3716}
3717
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003718
3719
3720#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003721/**---------------------------------------------------------------------------
3722
3723 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3724
3725 This function parses the ccx beacon request passed in the format
3726 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3727 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3728 <space>Scan Mode N<space>Meas Duration N
3729 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3730 then take N.
3731 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3732 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3733 This function does not take care of removing duplicate channels from the list
3734
3735 \param - pValue Pointer to data
3736 \param - pCcxBcnReq output pointer to store parsed ie information
3737
3738 \return - 0 for success non-zero for failure
3739
3740 --------------------------------------------------------------------------*/
3741static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3742 tCsrCcxBeaconReq *pCcxBcnReq)
3743{
3744 tANI_U8 *inPtr = pValue;
3745 int tempInt = 0;
3746 int j = 0, i = 0, v = 0;
3747 char buf[32];
3748
3749 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3750 /*no argument after the command*/
3751 if (NULL == inPtr)
3752 {
3753 return -EINVAL;
3754 }
3755 /*no space after the command*/
3756 else if (SPACE_ASCII_VALUE != *inPtr)
3757 {
3758 return -EINVAL;
3759 }
3760
3761 /*removing empty spaces*/
3762 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3763
3764 /*no argument followed by spaces*/
3765 if ('\0' == *inPtr) return -EINVAL;
3766
3767 /*getting the first argument ie measurement token*/
3768 v = sscanf(inPtr, "%32s ", buf);
3769 if (1 != v) return -EINVAL;
3770
3771 v = kstrtos32(buf, 10, &tempInt);
3772 if ( v < 0) return -EINVAL;
3773
3774 pCcxBcnReq->numBcnReqIe = tempInt;
3775
3776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3777 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3778
3779 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3780 {
3781 for (i = 0; i < 4; i++)
3782 {
3783 /*inPtr pointing to the beginning of first space after number of ie fields*/
3784 inPtr = strpbrk( inPtr, " " );
3785 /*no ie data after the number of ie fields argument*/
3786 if (NULL == inPtr) return -EINVAL;
3787
3788 /*removing empty space*/
3789 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3790
3791 /*no ie data after the number of ie fields argument and spaces*/
3792 if ( '\0' == *inPtr ) return -EINVAL;
3793
3794 v = sscanf(inPtr, "%32s ", buf);
3795 if (1 != v) return -EINVAL;
3796
3797 v = kstrtos32(buf, 10, &tempInt);
3798 if (v < 0) return -EINVAL;
3799
3800 switch (i)
3801 {
3802 case 0: /* Measurement token */
3803 if (tempInt <= 0)
3804 {
3805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3806 "Invalid Measurement Token(%d)", tempInt);
3807 return -EINVAL;
3808 }
3809 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3810 break;
3811
3812 case 1: /* Channel number */
3813 if ((tempInt <= 0) ||
3814 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3815 {
3816 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3817 "Invalid Channel Number(%d)", tempInt);
3818 return -EINVAL;
3819 }
3820 pCcxBcnReq->bcnReq[j].channel = tempInt;
3821 break;
3822
3823 case 2: /* Scan mode */
3824 if ((tempInt < 0) || (tempInt > 2))
3825 {
3826 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3827 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3828 return -EINVAL;
3829 }
3830 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3831 break;
3832
3833 case 3: /* Measurement duration */
3834 if (tempInt <= 0)
3835 {
3836 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3837 "Invalid Measurement Duration(%d)", tempInt);
3838 return -EINVAL;
3839 }
3840 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3841 break;
3842 }
3843 }
3844 }
3845
3846 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3847 {
3848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3849 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3850 j,
3851 pCcxBcnReq->bcnReq[j].measurementToken,
3852 pCcxBcnReq->bcnReq[j].channel,
3853 pCcxBcnReq->bcnReq[j].scanMode,
3854 pCcxBcnReq->bcnReq[j].measurementDuration);
3855 }
3856
3857 return VOS_STATUS_SUCCESS;
3858}
3859
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003860static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3861{
3862 struct statsContext *pStatsContext = NULL;
3863 hdd_adapter_t *pAdapter = NULL;
3864
3865 if (NULL == pContext)
3866 {
3867 hddLog(VOS_TRACE_LEVEL_ERROR,
3868 "%s: Bad param, pContext [%p]",
3869 __func__, pContext);
3870 return;
3871 }
3872
3873 /* there is a race condition that exists between this callback function
3874 and the caller since the caller could time out either before or
3875 while this code is executing. we'll assume the timeout hasn't
3876 occurred, but we'll verify that right before we save our work */
3877
3878 pStatsContext = pContext;
3879 pAdapter = pStatsContext->pAdapter;
3880 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3881 {
3882 /* the caller presumably timed out so there is nothing we can do */
3883 hddLog(VOS_TRACE_LEVEL_WARN,
3884 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3885 __func__, pAdapter, pStatsContext->magic);
3886 return;
3887 }
3888
3889 /* the race is on. caller could have timed out immediately after
3890 we verified the magic, but if so, caller will wait a short time
3891 for us to copy over the tsm stats */
3892 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3893 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3894 tsmMetrics.UplinkPktQueueDlyHist,
3895 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3896 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3897 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3898 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3899 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3900 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3901 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3902
3903 /* and notify the caller */
3904 complete(&pStatsContext->completion);
3905}
3906
3907
3908
3909static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3910 tAniTrafStrmMetrics* pTsmMetrics)
3911{
3912 hdd_station_ctx_t *pHddStaCtx = NULL;
3913 eHalStatus hstatus;
3914 long lrc;
3915 struct statsContext context;
3916 hdd_context_t *pHddCtx = NULL;
3917
3918 if (NULL == pAdapter)
3919 {
3920 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3921 return VOS_STATUS_E_FAULT;
3922 }
3923
3924 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3925 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3926
3927 /* we are connected prepare our callback context */
3928 init_completion(&context.completion);
3929 context.pAdapter = pAdapter;
3930 context.magic = STATS_CONTEXT_MAGIC;
3931
3932 /* query tsm stats */
3933 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3934 pHddStaCtx->conn_info.staId[ 0 ],
3935 pHddStaCtx->conn_info.bssId,
3936 &context, pHddCtx->pvosContext, tid);
3937
3938 if (eHAL_STATUS_SUCCESS != hstatus)
3939 {
3940 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3941 return hstatus;
3942 }
3943 else
3944 {
3945 /* request was sent -- wait for the response */
3946 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3947 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3948 /* either we have a response or we timed out
3949 either way, first invalidate our magic */
3950 context.magic = 0;
3951 if (lrc <= 0)
3952 {
3953 hddLog(VOS_TRACE_LEVEL_ERROR,
3954 "%s: SME %s while retrieving statistics",
3955 __func__, (0 == lrc) ? "timeout" : "interrupt");
3956 /* there is a race condition such that the callback
3957 function could be executing at the same time we are. of
3958 primary concern is if the callback function had already
3959 verified the "magic" but hasn't yet set the completion
3960 variable. Since the completion variable is on our
3961 stack, we'll delay just a bit to make sure the data is
3962 still valid if that is the case */
3963 msleep(50);
3964 return (VOS_STATUS_E_TIMEOUT);
3965 }
3966 }
3967 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3968 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3969 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3970 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3971 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3972 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3973 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3974 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3975 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3976 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3977
3978 return VOS_STATUS_SUCCESS;
3979}
3980#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3981
Srinivas Girigowdade697412013-02-14 16:31:48 -08003982#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3983void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3984{
3985 eCsrBand band = -1;
3986 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3987 switch (band)
3988 {
3989 case eCSR_BAND_ALL:
3990 *pBand = WLAN_HDD_UI_BAND_AUTO;
3991 break;
3992
3993 case eCSR_BAND_24:
3994 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3995 break;
3996
3997 case eCSR_BAND_5G:
3998 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3999 break;
4000
4001 default:
4002 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4003 *pBand = -1;
4004 break;
4005 }
4006}
4007
4008/**---------------------------------------------------------------------------
4009
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004010 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4011
4012 This function parses the send action frame data passed in the format
4013 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4014
Srinivas Girigowda56076852013-08-20 14:00:50 -07004015 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004016 \param - pTargetApBssid Pointer to target Ap bssid
4017 \param - pChannel Pointer to the Target AP channel
4018 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4019 \param - pBuf Pointer to data
4020 \param - pBufLen Pointer to data length
4021
4022 \return - 0 for success non-zero for failure
4023
4024 --------------------------------------------------------------------------*/
4025VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4026 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4027{
4028 tANI_U8 *inPtr = pValue;
4029 tANI_U8 *dataEnd;
4030 int tempInt;
4031 int j = 0;
4032 int i = 0;
4033 int v = 0;
4034 tANI_U8 tempBuf[32];
4035 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004036 /* 12 hexa decimal digits and 5 ':' */
4037 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004038
4039 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4040 /*no argument after the command*/
4041 if (NULL == inPtr)
4042 {
4043 return -EINVAL;
4044 }
4045
4046 /*no space after the command*/
4047 else if (SPACE_ASCII_VALUE != *inPtr)
4048 {
4049 return -EINVAL;
4050 }
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
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004061 v = sscanf(inPtr, "%17s", macAddress);
4062 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004063 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004064 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4065 "Invalid MAC address or All hex inputs are not read (%d)", v);
4066 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004067 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004068
4069 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4070 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4071 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4072 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4073 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4074 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004075
4076 /* point to the next argument */
4077 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4078 /*no argument after the command*/
4079 if (NULL == inPtr) return -EINVAL;
4080
4081 /*removing empty spaces*/
4082 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4083
4084 /*no argument followed by spaces*/
4085 if ('\0' == *inPtr)
4086 {
4087 return -EINVAL;
4088 }
4089
4090 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004091 v = sscanf(inPtr, "%32s ", tempBuf);
4092 if (1 != v) return -EINVAL;
4093
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004094 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304095 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4096 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004097
4098 *pChannel = tempInt;
4099
4100 /* point to the next argument */
4101 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4102 /*no argument after the command*/
4103 if (NULL == inPtr) return -EINVAL;
4104 /*removing empty spaces*/
4105 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4106
4107 /*no argument followed by spaces*/
4108 if ('\0' == *inPtr)
4109 {
4110 return -EINVAL;
4111 }
4112
4113 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004114 v = sscanf(inPtr, "%32s ", tempBuf);
4115 if (1 != v) return -EINVAL;
4116
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004117 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304118 if ( v < 0 || tempInt <= 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004119
4120 *pDwellTime = tempInt;
4121
4122 /* point to the next argument */
4123 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4124 /*no argument after the command*/
4125 if (NULL == inPtr) return -EINVAL;
4126 /*removing empty spaces*/
4127 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4128
4129 /*no argument followed by spaces*/
4130 if ('\0' == *inPtr)
4131 {
4132 return -EINVAL;
4133 }
4134
4135 /* find the length of data */
4136 dataEnd = inPtr;
4137 while(('\0' != *dataEnd) )
4138 {
4139 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004140 }
Kiet Lambe150c22013-11-21 16:30:32 +05304141 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004142 if ( *pBufLen <= 0) return -EINVAL;
4143
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004144 /* Allocate the number of bytes based on the number of input characters
4145 whether it is even or odd.
4146 if the number of input characters are even, then we need N/2 byte.
4147 if the number of input characters are odd, then we need do (N+1)/2 to
4148 compensate rounding off.
4149 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4150 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4151 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004152 if (NULL == *pBuf)
4153 {
4154 hddLog(VOS_TRACE_LEVEL_FATAL,
4155 "%s: vos_mem_alloc failed ", __func__);
4156 return -EINVAL;
4157 }
4158
4159 /* the buffer received from the upper layer is character buffer,
4160 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4161 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4162 and f0 in 3rd location */
4163 for (i = 0, j = 0; j < *pBufLen; j += 2)
4164 {
Kiet Lambe150c22013-11-21 16:30:32 +05304165 if( j+1 == *pBufLen)
4166 {
4167 tempByte = hdd_parse_hex(inPtr[j]);
4168 }
4169 else
4170 {
4171 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4172 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004173 (*pBuf)[i++] = tempByte;
4174 }
4175 *pBufLen = i;
4176 return VOS_STATUS_SUCCESS;
4177}
4178
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004179/**---------------------------------------------------------------------------
4180
Srinivas Girigowdade697412013-02-14 16:31:48 -08004181 \brief hdd_parse_channellist() - HDD Parse channel list
4182
4183 This function parses the channel list passed in the format
4184 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004185 if the Number of channels (N) does not match with the actual number of channels passed
4186 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4187 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4188 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4189 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004190
4191 \param - pValue Pointer to input channel list
4192 \param - ChannelList Pointer to local output array to record channel list
4193 \param - pNumChannels Pointer to number of roam scan channels
4194
4195 \return - 0 for success non-zero for failure
4196
4197 --------------------------------------------------------------------------*/
4198VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4199{
4200 tANI_U8 *inPtr = pValue;
4201 int tempInt;
4202 int j = 0;
4203 int v = 0;
4204 char buf[32];
4205
4206 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4207 /*no argument after the command*/
4208 if (NULL == inPtr)
4209 {
4210 return -EINVAL;
4211 }
4212
4213 /*no space after the command*/
4214 else if (SPACE_ASCII_VALUE != *inPtr)
4215 {
4216 return -EINVAL;
4217 }
4218
4219 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004220 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004221
4222 /*no argument followed by spaces*/
4223 if ('\0' == *inPtr)
4224 {
4225 return -EINVAL;
4226 }
4227
4228 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004229 v = sscanf(inPtr, "%32s ", buf);
4230 if (1 != v) return -EINVAL;
4231
Srinivas Girigowdade697412013-02-14 16:31:48 -08004232 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004233 if ((v < 0) ||
4234 (tempInt <= 0) ||
4235 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4236 {
4237 return -EINVAL;
4238 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004239
4240 *pNumChannels = tempInt;
4241
4242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4243 "Number of channels are: %d", *pNumChannels);
4244
4245 for (j = 0; j < (*pNumChannels); j++)
4246 {
4247 /*inPtr pointing to the beginning of first space after number of channels*/
4248 inPtr = strpbrk( inPtr, " " );
4249 /*no channel list after the number of channels argument*/
4250 if (NULL == inPtr)
4251 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004252 if (0 != j)
4253 {
4254 *pNumChannels = j;
4255 return VOS_STATUS_SUCCESS;
4256 }
4257 else
4258 {
4259 return -EINVAL;
4260 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004261 }
4262
4263 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004264 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004265
4266 /*no channel list after the number of channels argument and spaces*/
4267 if ( '\0' == *inPtr )
4268 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004269 if (0 != j)
4270 {
4271 *pNumChannels = j;
4272 return VOS_STATUS_SUCCESS;
4273 }
4274 else
4275 {
4276 return -EINVAL;
4277 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004278 }
4279
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004280 v = sscanf(inPtr, "%32s ", buf);
4281 if (1 != v) return -EINVAL;
4282
Srinivas Girigowdade697412013-02-14 16:31:48 -08004283 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004284 if ((v < 0) ||
4285 (tempInt <= 0) ||
4286 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4287 {
4288 return -EINVAL;
4289 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004290 pChannelList[j] = tempInt;
4291
4292 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4293 "Channel %d added to preferred channel list",
4294 pChannelList[j] );
4295 }
4296
Srinivas Girigowdade697412013-02-14 16:31:48 -08004297 return VOS_STATUS_SUCCESS;
4298}
4299
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004300
4301/**---------------------------------------------------------------------------
4302
4303 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4304
4305 This function parses the reasoc command data passed in the format
4306 REASSOC<space><bssid><space><channel>
4307
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004308 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004309 \param - pTargetApBssid Pointer to target Ap bssid
4310 \param - pChannel Pointer to the Target AP channel
4311
4312 \return - 0 for success non-zero for failure
4313
4314 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004315VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4316 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004317{
4318 tANI_U8 *inPtr = pValue;
4319 int tempInt;
4320 int v = 0;
4321 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004322 /* 12 hexa decimal digits and 5 ':' */
4323 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004324
4325 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4326 /*no argument after the command*/
4327 if (NULL == inPtr)
4328 {
4329 return -EINVAL;
4330 }
4331
4332 /*no space after the command*/
4333 else if (SPACE_ASCII_VALUE != *inPtr)
4334 {
4335 return -EINVAL;
4336 }
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
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004347 v = sscanf(inPtr, "%17s", macAddress);
4348 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004349 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004350 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4351 "Invalid MAC address or All hex inputs are not read (%d)", v);
4352 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004353 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004354
4355 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4356 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4357 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4358 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4359 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4360 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004361
4362 /* point to the next argument */
4363 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4364 /*no argument after the command*/
4365 if (NULL == inPtr) return -EINVAL;
4366
4367 /*removing empty spaces*/
4368 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4369
4370 /*no argument followed by spaces*/
4371 if ('\0' == *inPtr)
4372 {
4373 return -EINVAL;
4374 }
4375
4376 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004377 v = sscanf(inPtr, "%32s ", tempBuf);
4378 if (1 != v) return -EINVAL;
4379
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004380 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004381 if ((v < 0) ||
4382 (tempInt <= 0) ||
4383 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4384 {
4385 return -EINVAL;
4386 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004387
4388 *pChannel = tempInt;
4389 return VOS_STATUS_SUCCESS;
4390}
4391
4392#endif
4393
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004394#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4395/**---------------------------------------------------------------------------
4396
4397 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4398
4399 This function parses the SETCCKM IE command
4400 SETCCKMIE<space><ie data>
4401
4402 \param - pValue Pointer to input data
4403 \param - pCckmIe Pointer to output cckm Ie
4404 \param - pCckmIeLen Pointer to output cckm ie length
4405
4406 \return - 0 for success non-zero for failure
4407
4408 --------------------------------------------------------------------------*/
4409VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4410 tANI_U8 *pCckmIeLen)
4411{
4412 tANI_U8 *inPtr = pValue;
4413 tANI_U8 *dataEnd;
4414 int j = 0;
4415 int i = 0;
4416 tANI_U8 tempByte = 0;
4417
4418 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4419 /*no argument after the command*/
4420 if (NULL == inPtr)
4421 {
4422 return -EINVAL;
4423 }
4424
4425 /*no space after the command*/
4426 else if (SPACE_ASCII_VALUE != *inPtr)
4427 {
4428 return -EINVAL;
4429 }
4430
4431 /*removing empty spaces*/
4432 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4433
4434 /*no argument followed by spaces*/
4435 if ('\0' == *inPtr)
4436 {
4437 return -EINVAL;
4438 }
4439
4440 /* find the length of data */
4441 dataEnd = inPtr;
4442 while(('\0' != *dataEnd) )
4443 {
4444 dataEnd++;
4445 ++(*pCckmIeLen);
4446 }
4447 if ( *pCckmIeLen <= 0) return -EINVAL;
4448
4449 /* Allocate the number of bytes based on the number of input characters
4450 whether it is even or odd.
4451 if the number of input characters are even, then we need N/2 byte.
4452 if the number of input characters are odd, then we need do (N+1)/2 to
4453 compensate rounding off.
4454 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4455 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4456 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4457 if (NULL == *pCckmIe)
4458 {
4459 hddLog(VOS_TRACE_LEVEL_FATAL,
4460 "%s: vos_mem_alloc failed ", __func__);
4461 return -EINVAL;
4462 }
4463 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4464 /* the buffer received from the upper layer is character buffer,
4465 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4466 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4467 and f0 in 3rd location */
4468 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4469 {
4470 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4471 (*pCckmIe)[i++] = tempByte;
4472 }
4473 *pCckmIeLen = i;
4474
4475 return VOS_STATUS_SUCCESS;
4476}
4477#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4478
Jeff Johnson295189b2012-06-20 16:38:30 -07004479/**---------------------------------------------------------------------------
4480
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004481 \brief hdd_is_valid_mac_address() - Validate MAC address
4482
4483 This function validates whether the given MAC address is valid or not
4484 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4485 where X is the hexa decimal digit character and separated by ':'
4486 This algorithm works even if MAC address is not separated by ':'
4487
4488 This code checks given input string mac contains exactly 12 hexadecimal digits.
4489 and a separator colon : appears in the input string only after
4490 an even number of hex digits.
4491
4492 \param - pMacAddr pointer to the input MAC address
4493 \return - 1 for valid and 0 for invalid
4494
4495 --------------------------------------------------------------------------*/
4496
4497v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4498{
4499 int xdigit = 0;
4500 int separator = 0;
4501 while (*pMacAddr)
4502 {
4503 if (isxdigit(*pMacAddr))
4504 {
4505 xdigit++;
4506 }
4507 else if (':' == *pMacAddr)
4508 {
4509 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4510 break;
4511
4512 ++separator;
4513 }
4514 else
4515 {
4516 separator = -1;
4517 /* Invalid MAC found */
4518 return 0;
4519 }
4520 ++pMacAddr;
4521 }
4522 return (xdigit == 12 && (separator == 5 || separator == 0));
4523}
4524
4525/**---------------------------------------------------------------------------
4526
Jeff Johnson295189b2012-06-20 16:38:30 -07004527 \brief hdd_open() - HDD Open function
4528
4529 This is called in response to ifconfig up
4530
4531 \param - dev Pointer to net_device structure
4532
4533 \return - 0 for success non-zero for failure
4534
4535 --------------------------------------------------------------------------*/
4536int hdd_open (struct net_device *dev)
4537{
4538 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4539 hdd_context_t *pHddCtx;
4540 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4541 VOS_STATUS status;
4542 v_BOOL_t in_standby = TRUE;
4543
4544 if (NULL == pAdapter)
4545 {
4546 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004547 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004548 return -ENODEV;
4549 }
4550
4551 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4552 if (NULL == pHddCtx)
4553 {
4554 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004555 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004556 return -ENODEV;
4557 }
4558
4559 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4560 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4561 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004562 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4563 {
4564 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304565 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004566 in_standby = FALSE;
4567 break;
4568 }
4569 else
4570 {
4571 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4572 pAdapterNode = pNext;
4573 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004574 }
4575
4576 if (TRUE == in_standby)
4577 {
4578 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4579 {
4580 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4581 "wlan out of power save", __func__);
4582 return -EINVAL;
4583 }
4584 }
4585
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004586 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004587 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4588 {
4589 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004590 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004591 /* Enable TX queues only when we are connected */
4592 netif_tx_start_all_queues(dev);
4593 }
4594
4595 return 0;
4596}
4597
4598int hdd_mon_open (struct net_device *dev)
4599{
4600 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4601
4602 if(pAdapter == NULL) {
4603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004604 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004605 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004606 }
4607
4608 netif_start_queue(dev);
4609
4610 return 0;
4611}
4612/**---------------------------------------------------------------------------
4613
4614 \brief hdd_stop() - HDD stop function
4615
4616 This is called in response to ifconfig down
4617
4618 \param - dev Pointer to net_device structure
4619
4620 \return - 0 for success non-zero for failure
4621
4622 --------------------------------------------------------------------------*/
4623
4624int hdd_stop (struct net_device *dev)
4625{
4626 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4627 hdd_context_t *pHddCtx;
4628 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4629 VOS_STATUS status;
4630 v_BOOL_t enter_standby = TRUE;
4631
4632 ENTER();
4633
4634 if (NULL == pAdapter)
4635 {
4636 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004637 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004638 return -ENODEV;
4639 }
4640
4641 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4642 if (NULL == pHddCtx)
4643 {
4644 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004645 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004646 return -ENODEV;
4647 }
4648
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004649 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004650 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4651 netif_tx_disable(pAdapter->dev);
4652 netif_carrier_off(pAdapter->dev);
4653
4654
4655 /* SoftAP ifaces should never go in power save mode
4656 making sure same here. */
4657 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4658 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004659 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004660 )
4661 {
4662 /* SoftAP mode, so return from here */
4663 EXIT();
4664 return 0;
4665 }
4666
4667 /* Find if any iface is up then
4668 if any iface is up then can't put device to sleep/ power save mode. */
4669 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4670 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4671 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004672 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4673 {
4674 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304675 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004676 enter_standby = FALSE;
4677 break;
4678 }
4679 else
4680 {
4681 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4682 pAdapterNode = pNext;
4683 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004684 }
4685
4686 if (TRUE == enter_standby)
4687 {
4688 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4689 "entering standby", __func__);
4690 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4691 {
4692 /*log and return success*/
4693 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4694 "wlan in power save", __func__);
4695 }
4696 }
4697
4698 EXIT();
4699 return 0;
4700}
4701
4702/**---------------------------------------------------------------------------
4703
4704 \brief hdd_uninit() - HDD uninit function
4705
4706 This is called during the netdev unregister to uninitialize all data
4707associated with the device
4708
4709 \param - dev Pointer to net_device structure
4710
4711 \return - void
4712
4713 --------------------------------------------------------------------------*/
4714static void hdd_uninit (struct net_device *dev)
4715{
4716 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4717
4718 ENTER();
4719
4720 do
4721 {
4722 if (NULL == pAdapter)
4723 {
4724 hddLog(VOS_TRACE_LEVEL_FATAL,
4725 "%s: NULL pAdapter", __func__);
4726 break;
4727 }
4728
4729 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4730 {
4731 hddLog(VOS_TRACE_LEVEL_FATAL,
4732 "%s: Invalid magic", __func__);
4733 break;
4734 }
4735
4736 if (NULL == pAdapter->pHddCtx)
4737 {
4738 hddLog(VOS_TRACE_LEVEL_FATAL,
4739 "%s: NULL pHddCtx", __func__);
4740 break;
4741 }
4742
4743 if (dev != pAdapter->dev)
4744 {
4745 hddLog(VOS_TRACE_LEVEL_FATAL,
4746 "%s: Invalid device reference", __func__);
4747 /* we haven't validated all cases so let this go for now */
4748 }
4749
4750 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4751
4752 /* after uninit our adapter structure will no longer be valid */
4753 pAdapter->dev = NULL;
4754 pAdapter->magic = 0;
4755 } while (0);
4756
4757 EXIT();
4758}
4759
4760/**---------------------------------------------------------------------------
4761
4762 \brief hdd_release_firmware() -
4763
4764 This function calls the release firmware API to free the firmware buffer.
4765
4766 \param - pFileName Pointer to the File Name.
4767 pCtx - Pointer to the adapter .
4768
4769
4770 \return - 0 for success, non zero for failure
4771
4772 --------------------------------------------------------------------------*/
4773
4774VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4775{
4776 VOS_STATUS status = VOS_STATUS_SUCCESS;
4777 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4778 ENTER();
4779
4780
4781 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4782
4783 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4784
4785 if(pHddCtx->fw) {
4786 release_firmware(pHddCtx->fw);
4787 pHddCtx->fw = NULL;
4788 }
4789 else
4790 status = VOS_STATUS_E_FAILURE;
4791 }
4792 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4793 if(pHddCtx->nv) {
4794 release_firmware(pHddCtx->nv);
4795 pHddCtx->nv = NULL;
4796 }
4797 else
4798 status = VOS_STATUS_E_FAILURE;
4799
4800 }
4801
4802 EXIT();
4803 return status;
4804}
4805
4806/**---------------------------------------------------------------------------
4807
4808 \brief hdd_request_firmware() -
4809
4810 This function reads the firmware file using the request firmware
4811 API and returns the the firmware data and the firmware file size.
4812
4813 \param - pfileName - Pointer to the file name.
4814 - pCtx - Pointer to the adapter .
4815 - ppfw_data - Pointer to the pointer of the firmware data.
4816 - pSize - Pointer to the file size.
4817
4818 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4819
4820 --------------------------------------------------------------------------*/
4821
4822
4823VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4824{
4825 int status;
4826 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4827 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4828 ENTER();
4829
4830 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4831
4832 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4833
4834 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4835 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4836 __func__, pfileName);
4837 retval = VOS_STATUS_E_FAILURE;
4838 }
4839
4840 else {
4841 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4842 *pSize = pHddCtx->fw->size;
4843 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4844 __func__, *pSize);
4845 }
4846 }
4847 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4848
4849 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4850
4851 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4852 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4853 __func__, pfileName);
4854 retval = VOS_STATUS_E_FAILURE;
4855 }
4856
4857 else {
4858 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4859 *pSize = pHddCtx->nv->size;
4860 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4861 __func__, *pSize);
4862 }
4863 }
4864
4865 EXIT();
4866 return retval;
4867}
4868/**---------------------------------------------------------------------------
4869 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4870
4871 This is the function invoked by SME to inform the result of a full power
4872 request issued by HDD
4873
4874 \param - callbackcontext - Pointer to cookie
4875 status - result of request
4876
4877 \return - None
4878
4879--------------------------------------------------------------------------*/
4880void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4881{
4882 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4883
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004884 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004885 if(&pHddCtx->full_pwr_comp_var)
4886 {
4887 complete(&pHddCtx->full_pwr_comp_var);
4888 }
4889}
4890
4891/**---------------------------------------------------------------------------
4892
4893 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4894
4895 This is the function invoked by SME to inform the result of BMPS
4896 request issued by HDD
4897
4898 \param - callbackcontext - Pointer to cookie
4899 status - result of request
4900
4901 \return - None
4902
4903--------------------------------------------------------------------------*/
4904void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4905{
4906
4907 struct completion *completion_var = (struct completion*) callbackContext;
4908
Arif Hussain6d2a3322013-11-17 19:50:10 -08004909 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004910 if(completion_var != NULL)
4911 {
4912 complete(completion_var);
4913 }
4914}
4915
4916/**---------------------------------------------------------------------------
4917
4918 \brief hdd_get_cfg_file_size() -
4919
4920 This function reads the configuration file using the request firmware
4921 API and returns the configuration file size.
4922
4923 \param - pCtx - Pointer to the adapter .
4924 - pFileName - Pointer to the file name.
4925 - pBufSize - Pointer to the buffer size.
4926
4927 \return - 0 for success, non zero for failure
4928
4929 --------------------------------------------------------------------------*/
4930
4931VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4932{
4933 int status;
4934 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4935
4936 ENTER();
4937
4938 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4939
4940 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4941 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4942 status = VOS_STATUS_E_FAILURE;
4943 }
4944 else {
4945 *pBufSize = pHddCtx->fw->size;
4946 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4947 release_firmware(pHddCtx->fw);
4948 pHddCtx->fw = NULL;
4949 }
4950
4951 EXIT();
4952 return VOS_STATUS_SUCCESS;
4953}
4954
4955/**---------------------------------------------------------------------------
4956
4957 \brief hdd_read_cfg_file() -
4958
4959 This function reads the configuration file using the request firmware
4960 API and returns the cfg data and the buffer size of the configuration file.
4961
4962 \param - pCtx - Pointer to the adapter .
4963 - pFileName - Pointer to the file name.
4964 - pBuffer - Pointer to the data buffer.
4965 - pBufSize - Pointer to the buffer size.
4966
4967 \return - 0 for success, non zero for failure
4968
4969 --------------------------------------------------------------------------*/
4970
4971VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4972 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4973{
4974 int status;
4975 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4976
4977 ENTER();
4978
4979 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4980
4981 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4982 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4983 return VOS_STATUS_E_FAILURE;
4984 }
4985 else {
4986 if(*pBufSize != pHddCtx->fw->size) {
4987 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4988 "file size", __func__);
4989 release_firmware(pHddCtx->fw);
4990 pHddCtx->fw = NULL;
4991 return VOS_STATUS_E_FAILURE;
4992 }
4993 else {
4994 if(pBuffer) {
4995 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4996 }
4997 release_firmware(pHddCtx->fw);
4998 pHddCtx->fw = NULL;
4999 }
5000 }
5001
5002 EXIT();
5003
5004 return VOS_STATUS_SUCCESS;
5005}
5006
5007/**---------------------------------------------------------------------------
5008
Jeff Johnson295189b2012-06-20 16:38:30 -07005009 \brief hdd_set_mac_address() -
5010
5011 This function sets the user specified mac address using
5012 the command ifconfig wlanX hw ether <mac adress>.
5013
5014 \param - dev - Pointer to the net device.
5015 - addr - Pointer to the sockaddr.
5016 \return - 0 for success, non zero for failure
5017
5018 --------------------------------------------------------------------------*/
5019
5020static int hdd_set_mac_address(struct net_device *dev, void *addr)
5021{
5022 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5023 struct sockaddr *psta_mac_addr = addr;
5024 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5025
5026 ENTER();
5027
5028 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5029
5030#ifdef HDD_SESSIONIZE
5031 // set the MAC address though the STA ID CFG.
5032 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5033 (v_U8_t *)&pAdapter->macAddressCurrent,
5034 sizeof( pAdapter->macAddressCurrent ),
5035 hdd_set_mac_addr_cb, VOS_FALSE );
5036#endif
5037
5038 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5039
5040 EXIT();
5041 return halStatus;
5042}
5043
5044tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5045{
5046 int i;
5047 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5048 {
5049 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5050 break;
5051 }
5052
5053 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5054 return NULL;
5055
5056 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5057 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5058}
5059
5060void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5061{
5062 int i;
5063 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5064 {
5065 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5066 {
5067 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5068 break;
5069 }
5070 }
5071 return;
5072}
5073
5074#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5075 static struct net_device_ops wlan_drv_ops = {
5076 .ndo_open = hdd_open,
5077 .ndo_stop = hdd_stop,
5078 .ndo_uninit = hdd_uninit,
5079 .ndo_start_xmit = hdd_hard_start_xmit,
5080 .ndo_tx_timeout = hdd_tx_timeout,
5081 .ndo_get_stats = hdd_stats,
5082 .ndo_do_ioctl = hdd_ioctl,
5083 .ndo_set_mac_address = hdd_set_mac_address,
5084 .ndo_select_queue = hdd_select_queue,
5085#ifdef WLAN_FEATURE_PACKET_FILTERING
5086#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5087 .ndo_set_rx_mode = hdd_set_multicast_list,
5088#else
5089 .ndo_set_multicast_list = hdd_set_multicast_list,
5090#endif //LINUX_VERSION_CODE
5091#endif
5092 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005093 static struct net_device_ops wlan_mon_drv_ops = {
5094 .ndo_open = hdd_mon_open,
5095 .ndo_stop = hdd_stop,
5096 .ndo_uninit = hdd_uninit,
5097 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5098 .ndo_tx_timeout = hdd_tx_timeout,
5099 .ndo_get_stats = hdd_stats,
5100 .ndo_do_ioctl = hdd_ioctl,
5101 .ndo_set_mac_address = hdd_set_mac_address,
5102 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005103
5104#endif
5105
5106void hdd_set_station_ops( struct net_device *pWlanDev )
5107{
5108#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005109 pWlanDev->netdev_ops = &wlan_drv_ops;
5110#else
5111 pWlanDev->open = hdd_open;
5112 pWlanDev->stop = hdd_stop;
5113 pWlanDev->uninit = hdd_uninit;
5114 pWlanDev->hard_start_xmit = NULL;
5115 pWlanDev->tx_timeout = hdd_tx_timeout;
5116 pWlanDev->get_stats = hdd_stats;
5117 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005118 pWlanDev->set_mac_address = hdd_set_mac_address;
5119#endif
5120}
5121
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005122static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005123{
5124 struct net_device *pWlanDev = NULL;
5125 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005126 /*
5127 * cfg80211 initialization and registration....
5128 */
5129 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5130
Jeff Johnson295189b2012-06-20 16:38:30 -07005131 if(pWlanDev != NULL)
5132 {
5133
5134 //Save the pointer to the net_device in the HDD adapter
5135 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5136
Jeff Johnson295189b2012-06-20 16:38:30 -07005137 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5138
5139 pAdapter->dev = pWlanDev;
5140 pAdapter->pHddCtx = pHddCtx;
5141 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5142
5143 init_completion(&pAdapter->session_open_comp_var);
5144 init_completion(&pAdapter->session_close_comp_var);
5145 init_completion(&pAdapter->disconnect_comp_var);
5146 init_completion(&pAdapter->linkup_event_var);
5147 init_completion(&pAdapter->cancel_rem_on_chan_var);
5148 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005149#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5150 init_completion(&pAdapter->offchannel_tx_event);
5151#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005152 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005153#ifdef FEATURE_WLAN_TDLS
5154 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005155 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005156 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305157 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005158#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005159 init_completion(&pHddCtx->mc_sus_event_var);
5160 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305161 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005162 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005163 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005164
Rajeev79dbe4c2013-10-05 11:03:42 +05305165#ifdef FEATURE_WLAN_BATCH_SCAN
5166 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5167 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5168 pAdapter->pBatchScanRsp = NULL;
5169 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005170 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08005171 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305172 mutex_init(&pAdapter->hdd_batch_scan_lock);
5173#endif
5174
Jeff Johnson295189b2012-06-20 16:38:30 -07005175 pAdapter->isLinkUpSvcNeeded = FALSE;
5176 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5177 //Init the net_device structure
5178 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5179
5180 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5181 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5182 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5183 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5184
5185 hdd_set_station_ops( pAdapter->dev );
5186
5187 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005188 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5189 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5190 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005191 /* set pWlanDev's parent to underlying device */
5192 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5193 }
5194
5195 return pAdapter;
5196}
5197
5198VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5199{
5200 struct net_device *pWlanDev = pAdapter->dev;
5201 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5202 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5203 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5204
5205 if( rtnl_lock_held )
5206 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005207 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005208 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5209 {
5210 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5211 return VOS_STATUS_E_FAILURE;
5212 }
5213 }
5214 if (register_netdevice(pWlanDev))
5215 {
5216 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5217 return VOS_STATUS_E_FAILURE;
5218 }
5219 }
5220 else
5221 {
5222 if(register_netdev(pWlanDev))
5223 {
5224 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5225 return VOS_STATUS_E_FAILURE;
5226 }
5227 }
5228 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5229
5230 return VOS_STATUS_SUCCESS;
5231}
5232
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005233static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005234{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005235 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005236
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005237 if (NULL == pAdapter)
5238 {
5239 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5240 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005241 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005242
5243 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5244 {
5245 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5246 return eHAL_STATUS_NOT_INITIALIZED;
5247 }
5248
5249 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5250
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005251#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005252 /* need to make sure all of our scheduled work has completed.
5253 * This callback is called from MC thread context, so it is safe to
5254 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005255 *
5256 * Even though this is called from MC thread context, if there is a faulty
5257 * work item in the system, that can hang this call forever. So flushing
5258 * this global work queue is not safe; and now we make sure that
5259 * individual work queues are stopped correctly. But the cancel work queue
5260 * is a GPL only API, so the proprietary version of the driver would still
5261 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005262 */
5263 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005264#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005265
5266 /* We can be blocked while waiting for scheduled work to be
5267 * flushed, and the adapter structure can potentially be freed, in
5268 * which case the magic will have been reset. So make sure the
5269 * magic is still good, and hence the adapter structure is still
5270 * valid, before signaling completion */
5271 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5272 {
5273 complete(&pAdapter->session_close_comp_var);
5274 }
5275
Jeff Johnson295189b2012-06-20 16:38:30 -07005276 return eHAL_STATUS_SUCCESS;
5277}
5278
5279VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5280{
5281 struct net_device *pWlanDev = pAdapter->dev;
5282 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5283 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5284 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5285 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5286 int rc = 0;
5287
5288 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005289 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005290 //Open a SME session for future operation
5291 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005292 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005293 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5294 {
5295 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005296 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005297 halStatus, halStatus );
5298 status = VOS_STATUS_E_FAILURE;
5299 goto error_sme_open;
5300 }
5301
5302 //Block on a completion variable. Can't wait forever though.
5303 rc = wait_for_completion_interruptible_timeout(
5304 &pAdapter->session_open_comp_var,
5305 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5306 if (!rc)
5307 {
5308 hddLog(VOS_TRACE_LEVEL_FATAL,
5309 "Session is not opened within timeout period code %08d", rc );
5310 status = VOS_STATUS_E_FAILURE;
5311 goto error_sme_open;
5312 }
5313
5314 // Register wireless extensions
5315 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5316 {
5317 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005318 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005319 halStatus, halStatus );
5320 status = VOS_STATUS_E_FAILURE;
5321 goto error_register_wext;
5322 }
5323 //Safe to register the hard_start_xmit function again
5324#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5325 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5326#else
5327 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5328#endif
5329
5330 //Set the Connection State to Not Connected
5331 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5332
5333 //Set the default operation channel
5334 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5335
5336 /* Make the default Auth Type as OPEN*/
5337 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5338
5339 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5340 {
5341 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005342 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005343 status, status );
5344 goto error_init_txrx;
5345 }
5346
5347 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5348
5349 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5350 {
5351 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005352 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005353 status, status );
5354 goto error_wmm_init;
5355 }
5356
5357 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5358
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005359#ifdef FEATURE_WLAN_TDLS
5360 if(0 != wlan_hdd_tdls_init(pAdapter))
5361 {
5362 status = VOS_STATUS_E_FAILURE;
5363 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5364 goto error_tdls_init;
5365 }
5366 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5367#endif
5368
Jeff Johnson295189b2012-06-20 16:38:30 -07005369 return VOS_STATUS_SUCCESS;
5370
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005371#ifdef FEATURE_WLAN_TDLS
5372error_tdls_init:
5373 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5374 hdd_wmm_adapter_close(pAdapter);
5375#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005376error_wmm_init:
5377 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5378 hdd_deinit_tx_rx(pAdapter);
5379error_init_txrx:
5380 hdd_UnregisterWext(pWlanDev);
5381error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005382 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005383 {
5384 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005385 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005386 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005387 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005388 {
5389 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005390 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005391 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005392 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005393 }
5394}
5395error_sme_open:
5396 return status;
5397}
5398
Jeff Johnson295189b2012-06-20 16:38:30 -07005399void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5400{
5401 hdd_cfg80211_state_t *cfgState;
5402
5403 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5404
5405 if( NULL != cfgState->buf )
5406 {
5407 int rc;
5408 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5409 rc = wait_for_completion_interruptible_timeout(
5410 &pAdapter->tx_action_cnf_event,
5411 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5412 if(!rc)
5413 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005414 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005415 ("ERROR: HDD Wait for Action Confirmation Failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07005416 }
5417 }
5418 return;
5419}
Jeff Johnson295189b2012-06-20 16:38:30 -07005420
5421void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5422{
5423 ENTER();
5424 switch ( pAdapter->device_mode )
5425 {
5426 case WLAN_HDD_INFRA_STATION:
5427 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005428 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005429 {
5430 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5431 {
5432 hdd_deinit_tx_rx( pAdapter );
5433 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5434 }
5435
5436 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5437 {
5438 hdd_wmm_adapter_close( pAdapter );
5439 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5440 }
5441
Jeff Johnson295189b2012-06-20 16:38:30 -07005442 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005443#ifdef FEATURE_WLAN_TDLS
5444 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5445 {
5446 wlan_hdd_tdls_exit(pAdapter);
5447 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5448 }
5449#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005450
5451 break;
5452 }
5453
5454 case WLAN_HDD_SOFTAP:
5455 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005456 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305457
5458 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5459 {
5460 hdd_wmm_adapter_close( pAdapter );
5461 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5462 }
5463
Jeff Johnson295189b2012-06-20 16:38:30 -07005464 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005465
5466 hdd_unregister_hostapd(pAdapter);
5467 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005468 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005469 break;
5470 }
5471
5472 case WLAN_HDD_MONITOR:
5473 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005474 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005475 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5476 {
5477 hdd_deinit_tx_rx( pAdapter );
5478 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5479 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005480 if(NULL != pAdapterforTx)
5481 {
5482 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5483 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005484 break;
5485 }
5486
5487
5488 default:
5489 break;
5490 }
5491
5492 EXIT();
5493}
5494
5495void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5496{
5497 struct net_device *pWlanDev = pAdapter->dev;
5498
Rajeev79dbe4c2013-10-05 11:03:42 +05305499#ifdef FEATURE_WLAN_BATCH_SCAN
5500 tHddBatchScanRsp *pNode;
5501 tHddBatchScanRsp *pPrev;
5502 if (pAdapter)
5503 {
5504 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5505 pNode = pAdapter->pBatchScanRsp;
5506 while (pNode)
5507 {
5508 pPrev = pNode;
5509 pNode = pNode->pNext;
5510 vos_mem_free((v_VOID_t * )pPrev);
5511 }
5512 pAdapter->pBatchScanRsp = NULL;
5513 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5514 }
5515#endif
5516
Jeff Johnson295189b2012-06-20 16:38:30 -07005517 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5518 if( rtnl_held )
5519 {
5520 unregister_netdevice(pWlanDev);
5521 }
5522 else
5523 {
5524 unregister_netdev(pWlanDev);
5525 }
5526 // note that the pAdapter is no longer valid at this point
5527 // since the memory has been reclaimed
5528 }
5529
5530}
5531
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005532void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5533{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305534 VOS_STATUS status;
5535 hdd_adapter_t *pAdapter = NULL;
5536 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005537
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305538 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005539
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305540 /*loop through all adapters.*/
5541 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005542 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305543 pAdapter = pAdapterNode->pAdapter;
5544 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5545 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005546
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305547 { // we skip this registration for modes other than STA and P2P client modes.
5548 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5549 pAdapterNode = pNext;
5550 continue;
5551 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005552
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305553 //Apply Dynamic DTIM For P2P
5554 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5555 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5556 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5557 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5558 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5559 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5560 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5561 (eConnectionState_Associated ==
5562 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5563 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5564 {
5565 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005566
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305567 powerRequest.uIgnoreDTIM = 1;
5568 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5569
5570 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5571 {
5572 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5573 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5574 }
5575 else
5576 {
5577 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5578 }
5579
5580 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5581 * specified during Enter/Exit BMPS when LCD off*/
5582 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5583 NULL, eANI_BOOLEAN_FALSE);
5584 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5585 NULL, eANI_BOOLEAN_FALSE);
5586
5587 /* switch to the DTIM specified in cfg.ini */
5588 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5589 "Switch to DTIM %d", powerRequest.uListenInterval);
5590 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5591 break;
5592
5593 }
5594
5595 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5596 pAdapterNode = pNext;
5597 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005598}
5599
5600void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5601{
5602 /*Switch back to DTIM 1*/
5603 tSirSetPowerParamsReq powerRequest = { 0 };
5604
5605 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5606 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005607 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005608
5609 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5610 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5611 NULL, eANI_BOOLEAN_FALSE);
5612 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5613 NULL, eANI_BOOLEAN_FALSE);
5614
5615 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5616 "Switch to DTIM%d",powerRequest.uListenInterval);
5617 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5618
5619}
5620
Jeff Johnson295189b2012-06-20 16:38:30 -07005621VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5622{
5623 VOS_STATUS status = VOS_STATUS_SUCCESS;
5624
5625 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5626 {
5627 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5628 }
5629
5630 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5631 {
5632 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5633 }
5634
5635 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5636 {
5637 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5638 }
5639
5640 return status;
5641}
5642
5643VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5644{
5645 hdd_adapter_t *pAdapter = NULL;
5646 eHalStatus halStatus;
5647 VOS_STATUS status = VOS_STATUS_E_INVAL;
5648 v_BOOL_t disableBmps = FALSE;
5649 v_BOOL_t disableImps = FALSE;
5650
5651 switch(session_type)
5652 {
5653 case WLAN_HDD_INFRA_STATION:
5654 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005655 case WLAN_HDD_P2P_CLIENT:
5656 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005657 //Exit BMPS -> Is Sta/P2P Client is already connected
5658 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5659 if((NULL != pAdapter)&&
5660 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5661 {
5662 disableBmps = TRUE;
5663 }
5664
5665 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5666 if((NULL != pAdapter)&&
5667 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5668 {
5669 disableBmps = TRUE;
5670 }
5671
5672 //Exit both Bmps and Imps incase of Go/SAP Mode
5673 if((WLAN_HDD_SOFTAP == session_type) ||
5674 (WLAN_HDD_P2P_GO == session_type))
5675 {
5676 disableBmps = TRUE;
5677 disableImps = TRUE;
5678 }
5679
5680 if(TRUE == disableImps)
5681 {
5682 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5683 {
5684 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5685 }
5686 }
5687
5688 if(TRUE == disableBmps)
5689 {
5690 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5691 {
5692 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5693
5694 if(eHAL_STATUS_SUCCESS != halStatus)
5695 {
5696 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005697 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005698 VOS_ASSERT(0);
5699 return status;
5700 }
5701 }
5702
5703 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5704 {
5705 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5706
5707 if(eHAL_STATUS_SUCCESS != halStatus)
5708 {
5709 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005710 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005711 VOS_ASSERT(0);
5712 return status;
5713 }
5714 }
5715 }
5716
5717 if((TRUE == disableBmps) ||
5718 (TRUE == disableImps))
5719 {
5720 /* Now, get the chip into Full Power now */
5721 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5722 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5723 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5724
5725 if(halStatus != eHAL_STATUS_SUCCESS)
5726 {
5727 if(halStatus == eHAL_STATUS_PMC_PENDING)
5728 {
5729 //Block on a completion variable. Can't wait forever though
5730 wait_for_completion_interruptible_timeout(
5731 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5732 }
5733 else
5734 {
5735 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005736 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005737 VOS_ASSERT(0);
5738 return status;
5739 }
5740 }
5741
5742 status = VOS_STATUS_SUCCESS;
5743 }
5744
5745 break;
5746 }
5747 return status;
5748}
5749
5750hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005751 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005752 tANI_U8 rtnl_held )
5753{
5754 hdd_adapter_t *pAdapter = NULL;
5755 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5756 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5757 VOS_STATUS exitbmpsStatus;
5758
Arif Hussain6d2a3322013-11-17 19:50:10 -08005759 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005760
5761 //Disable BMPS incase of Concurrency
5762 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5763
5764 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5765 {
5766 //Fail to Exit BMPS
5767 VOS_ASSERT(0);
5768 return NULL;
5769 }
5770
5771 switch(session_type)
5772 {
5773 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005774 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005775 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005776 {
5777 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5778
5779 if( NULL == pAdapter )
5780 return NULL;
5781
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305782#ifdef FEATURE_WLAN_TDLS
5783 /* A Mutex Lock is introduced while changing/initializing the mode to
5784 * protect the concurrent access for the Adapters by TDLS module.
5785 */
5786 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5787 {
5788 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5789 "%s: unable to lock list", __func__);
5790 return NULL;
5791 }
5792#endif
5793
Jeff Johnsone7245742012-09-05 17:12:55 -07005794 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5795 NL80211_IFTYPE_P2P_CLIENT:
5796 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005797
Jeff Johnson295189b2012-06-20 16:38:30 -07005798 pAdapter->device_mode = session_type;
5799
5800 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305801#ifdef FEATURE_WLAN_TDLS
5802 mutex_unlock(&pHddCtx->tdls_lock);
5803#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005804 if( VOS_STATUS_SUCCESS != status )
5805 goto err_free_netdev;
5806
5807 status = hdd_register_interface( pAdapter, rtnl_held );
5808 if( VOS_STATUS_SUCCESS != status )
5809 {
5810 hdd_deinit_adapter(pHddCtx, pAdapter);
5811 goto err_free_netdev;
5812 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305813
5814#ifdef WLAN_NS_OFFLOAD
5815 // Workqueue which gets scheduled in IPv6 notification callback.
5816 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5817#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005818 //Stop the Interface TX queue.
5819 netif_tx_disable(pAdapter->dev);
5820 //netif_tx_disable(pWlanDev);
5821 netif_carrier_off(pAdapter->dev);
5822
5823 break;
5824 }
5825
Jeff Johnson295189b2012-06-20 16:38:30 -07005826 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 case WLAN_HDD_SOFTAP:
5828 {
5829 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5830 if( NULL == pAdapter )
5831 return NULL;
5832
Jeff Johnson295189b2012-06-20 16:38:30 -07005833 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5834 NL80211_IFTYPE_AP:
5835 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005836 pAdapter->device_mode = session_type;
5837
5838 status = hdd_init_ap_mode(pAdapter);
5839 if( VOS_STATUS_SUCCESS != status )
5840 goto err_free_netdev;
5841
5842 status = hdd_register_hostapd( pAdapter, rtnl_held );
5843 if( VOS_STATUS_SUCCESS != status )
5844 {
5845 hdd_deinit_adapter(pHddCtx, pAdapter);
5846 goto err_free_netdev;
5847 }
5848
5849 netif_tx_disable(pAdapter->dev);
5850 netif_carrier_off(pAdapter->dev);
5851
5852 hdd_set_conparam( 1 );
5853 break;
5854 }
5855 case WLAN_HDD_MONITOR:
5856 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005857 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5858 if( NULL == pAdapter )
5859 return NULL;
5860
5861 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5862 pAdapter->device_mode = session_type;
5863 status = hdd_register_interface( pAdapter, rtnl_held );
5864#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5865 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5866#else
5867 pAdapter->dev->open = hdd_mon_open;
5868 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5869#endif
5870 hdd_init_tx_rx( pAdapter );
5871 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5872 //Set adapter to be used for data tx. It will use either GO or softap.
5873 pAdapter->sessionCtx.monitor.pAdapterForTx =
5874 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005875 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5876 {
5877 pAdapter->sessionCtx.monitor.pAdapterForTx =
5878 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5879 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005880 /* This workqueue will be used to transmit management packet over
5881 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005882 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5883 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5884 return NULL;
5885 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005886
Jeff Johnson295189b2012-06-20 16:38:30 -07005887 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5888 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005889 }
5890 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005891 case WLAN_HDD_FTM:
5892 {
5893 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5894
5895 if( NULL == pAdapter )
5896 return NULL;
5897 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5898 * message while loading driver in FTM mode. */
5899 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5900 pAdapter->device_mode = session_type;
5901 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305902
5903 hdd_init_tx_rx( pAdapter );
5904
5905 //Stop the Interface TX queue.
5906 netif_tx_disable(pAdapter->dev);
5907 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005908 }
5909 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005910 default:
5911 {
5912 VOS_ASSERT(0);
5913 return NULL;
5914 }
5915 }
5916
Jeff Johnson295189b2012-06-20 16:38:30 -07005917 if( VOS_STATUS_SUCCESS == status )
5918 {
5919 //Add it to the hdd's session list.
5920 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5921 if( NULL == pHddAdapterNode )
5922 {
5923 status = VOS_STATUS_E_NOMEM;
5924 }
5925 else
5926 {
5927 pHddAdapterNode->pAdapter = pAdapter;
5928 status = hdd_add_adapter_back ( pHddCtx,
5929 pHddAdapterNode );
5930 }
5931 }
5932
5933 if( VOS_STATUS_SUCCESS != status )
5934 {
5935 if( NULL != pAdapter )
5936 {
5937 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5938 pAdapter = NULL;
5939 }
5940 if( NULL != pHddAdapterNode )
5941 {
5942 vos_mem_free( pHddAdapterNode );
5943 }
5944
5945 goto resume_bmps;
5946 }
5947
5948 if(VOS_STATUS_SUCCESS == status)
5949 {
5950 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5951
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005952 //Initialize the WoWL service
5953 if(!hdd_init_wowl(pAdapter))
5954 {
5955 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5956 goto err_free_netdev;
5957 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005958 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005959 return pAdapter;
5960
5961err_free_netdev:
5962 free_netdev(pAdapter->dev);
5963 wlan_hdd_release_intf_addr( pHddCtx,
5964 pAdapter->macAddressCurrent.bytes );
5965
5966resume_bmps:
5967 //If bmps disabled enable it
5968 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5969 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305970 if (pHddCtx->hdd_wlan_suspended)
5971 {
5972 hdd_set_pwrparams(pHddCtx);
5973 }
5974 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005975 }
5976 return NULL;
5977}
5978
5979VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5980 tANI_U8 rtnl_held )
5981{
5982 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5983 VOS_STATUS status;
5984
5985 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5986 if( VOS_STATUS_SUCCESS != status )
5987 return status;
5988
5989 while ( pCurrent->pAdapter != pAdapter )
5990 {
5991 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5992 if( VOS_STATUS_SUCCESS != status )
5993 break;
5994
5995 pCurrent = pNext;
5996 }
5997 pAdapterNode = pCurrent;
5998 if( VOS_STATUS_SUCCESS == status )
5999 {
6000 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6001 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306002
6003#ifdef FEATURE_WLAN_TDLS
6004
6005 /* A Mutex Lock is introduced while changing/initializing the mode to
6006 * protect the concurrent access for the Adapters by TDLS module.
6007 */
6008 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6009 {
6010 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6011 "%s: unable to lock list", __func__);
6012 return VOS_STATUS_E_FAILURE;
6013 }
6014#endif
6015
Jeff Johnson295189b2012-06-20 16:38:30 -07006016 hdd_remove_adapter( pHddCtx, pAdapterNode );
6017 vos_mem_free( pAdapterNode );
6018
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306019#ifdef FEATURE_WLAN_TDLS
6020 mutex_unlock(&pHddCtx->tdls_lock);
6021#endif
6022
Jeff Johnson295189b2012-06-20 16:38:30 -07006023
6024 /* If there is a single session of STA/P2P client, re-enable BMPS */
6025 if ((!vos_concurrent_sessions_running()) &&
6026 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6027 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6028 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306029 if (pHddCtx->hdd_wlan_suspended)
6030 {
6031 hdd_set_pwrparams(pHddCtx);
6032 }
6033 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006034 }
6035
6036 return VOS_STATUS_SUCCESS;
6037 }
6038
6039 return VOS_STATUS_E_FAILURE;
6040}
6041
6042VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6043{
6044 hdd_adapter_list_node_t *pHddAdapterNode;
6045 VOS_STATUS status;
6046
6047 ENTER();
6048
6049 do
6050 {
6051 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6052 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6053 {
6054 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6055 vos_mem_free( pHddAdapterNode );
6056 }
6057 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6058
6059 EXIT();
6060
6061 return VOS_STATUS_SUCCESS;
6062}
6063
6064void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6065{
6066 v_U8_t addIE[1] = {0};
6067
6068 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6069 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6070 eANI_BOOLEAN_FALSE) )
6071 {
6072 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006073 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006074 }
6075
6076 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6077 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6078 eANI_BOOLEAN_FALSE) )
6079 {
6080 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006081 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006082 }
6083
6084 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6085 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6086 eANI_BOOLEAN_FALSE) )
6087 {
6088 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006089 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006090 }
6091}
6092
6093VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6094{
6095 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6096 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6097 union iwreq_data wrqu;
6098
6099 ENTER();
6100
6101 switch(pAdapter->device_mode)
6102 {
6103 case WLAN_HDD_INFRA_STATION:
6104 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006105 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006106 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6107 {
6108 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6109 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6110 pAdapter->sessionId,
6111 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6112 else
6113 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6114 pAdapter->sessionId,
6115 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6116 //success implies disconnect command got queued up successfully
6117 if(halStatus == eHAL_STATUS_SUCCESS)
6118 {
6119 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6120 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6121 }
6122 memset(&wrqu, '\0', sizeof(wrqu));
6123 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6124 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6125 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6126 }
6127 else
6128 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306129 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006130 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306131#ifdef WLAN_OPEN_SOURCE
6132#ifdef WLAN_NS_OFFLOAD
6133 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6134#endif
6135#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006136
6137 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6138 {
6139 INIT_COMPLETION(pAdapter->session_close_comp_var);
6140 if (eHAL_STATUS_SUCCESS ==
6141 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6142 hdd_smeCloseSessionCallback, pAdapter))
6143 {
6144 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006145 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006146 &pAdapter->session_close_comp_var,
6147 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6148 }
6149 }
6150
6151 break;
6152
6153 case WLAN_HDD_SOFTAP:
6154 case WLAN_HDD_P2P_GO:
6155 //Any softap specific cleanup here...
6156 mutex_lock(&pHddCtx->sap_lock);
6157 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6158 {
6159 VOS_STATUS status;
6160 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6161
6162 //Stop Bss.
6163 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6164 if (VOS_IS_STATUS_SUCCESS(status))
6165 {
6166 hdd_hostapd_state_t *pHostapdState =
6167 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6168
6169 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6170
6171 if (!VOS_IS_STATUS_SUCCESS(status))
6172 {
6173 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006174 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006175 }
6176 }
6177 else
6178 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006179 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006180 }
6181 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6182
6183 if (eHAL_STATUS_FAILURE ==
6184 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6185 0, NULL, eANI_BOOLEAN_FALSE))
6186 {
6187 hddLog(LOGE,
6188 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006189 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006190 }
6191
6192 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6193 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6194 eANI_BOOLEAN_FALSE) )
6195 {
6196 hddLog(LOGE,
6197 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6198 }
6199
6200 // Reset WNI_CFG_PROBE_RSP Flags
6201 wlan_hdd_reset_prob_rspies(pAdapter);
6202 kfree(pAdapter->sessionCtx.ap.beacon);
6203 pAdapter->sessionCtx.ap.beacon = NULL;
6204 }
6205 mutex_unlock(&pHddCtx->sap_lock);
6206 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006207
Jeff Johnson295189b2012-06-20 16:38:30 -07006208 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006209#ifdef WLAN_OPEN_SOURCE
6210 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6211#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006212 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006213
Jeff Johnson295189b2012-06-20 16:38:30 -07006214 default:
6215 break;
6216 }
6217
6218 EXIT();
6219 return VOS_STATUS_SUCCESS;
6220}
6221
6222VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6223{
6224 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6225 VOS_STATUS status;
6226 hdd_adapter_t *pAdapter;
6227
6228 ENTER();
6229
6230 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6231
6232 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6233 {
6234 pAdapter = pAdapterNode->pAdapter;
6235 netif_tx_disable(pAdapter->dev);
6236 netif_carrier_off(pAdapter->dev);
6237
6238 hdd_stop_adapter( pHddCtx, pAdapter );
6239
6240 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6241 pAdapterNode = pNext;
6242 }
6243
6244 EXIT();
6245
6246 return VOS_STATUS_SUCCESS;
6247}
6248
6249VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6250{
6251 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6252 VOS_STATUS status;
6253 hdd_adapter_t *pAdapter;
6254
6255 ENTER();
6256
6257 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6258
6259 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6260 {
6261 pAdapter = pAdapterNode->pAdapter;
6262 netif_tx_disable(pAdapter->dev);
6263 netif_carrier_off(pAdapter->dev);
6264
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006265 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6266
Jeff Johnson295189b2012-06-20 16:38:30 -07006267 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306268 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6269 {
6270 hdd_wmm_adapter_close( pAdapter );
6271 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6272 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006273
6274 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6275 pAdapterNode = pNext;
6276 }
6277
6278 EXIT();
6279
6280 return VOS_STATUS_SUCCESS;
6281}
6282
6283VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6284{
6285 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6286 VOS_STATUS status;
6287 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306288 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006289
6290 ENTER();
6291
6292 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6293
6294 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6295 {
6296 pAdapter = pAdapterNode->pAdapter;
6297
6298 switch(pAdapter->device_mode)
6299 {
6300 case WLAN_HDD_INFRA_STATION:
6301 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006302 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306303
6304 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6305
Jeff Johnson295189b2012-06-20 16:38:30 -07006306 hdd_init_station_mode(pAdapter);
6307 /* Open the gates for HDD to receive Wext commands */
6308 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006309 pHddCtx->scan_info.mScanPending = FALSE;
6310 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006311
6312 //Trigger the initial scan
6313 hdd_wlan_initial_scan(pAdapter);
6314
6315 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306316 if (eConnectionState_Associated == connState ||
6317 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006318 {
6319 union iwreq_data wrqu;
6320 memset(&wrqu, '\0', sizeof(wrqu));
6321 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6322 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6323 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006324 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006325
Jeff Johnson295189b2012-06-20 16:38:30 -07006326 /* indicate disconnected event to nl80211 */
6327 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6328 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006329 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306330 else if (eConnectionState_Connecting == connState)
6331 {
6332 /*
6333 * Indicate connect failure to supplicant if we were in the
6334 * process of connecting
6335 */
6336 cfg80211_connect_result(pAdapter->dev, NULL,
6337 NULL, 0, NULL, 0,
6338 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6339 GFP_KERNEL);
6340 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006341 break;
6342
6343 case WLAN_HDD_SOFTAP:
6344 /* softAP can handle SSR */
6345 break;
6346
6347 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006348 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006349 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006350 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006351 break;
6352
6353 case WLAN_HDD_MONITOR:
6354 /* monitor interface start */
6355 break;
6356 default:
6357 break;
6358 }
6359
6360 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6361 pAdapterNode = pNext;
6362 }
6363
6364 EXIT();
6365
6366 return VOS_STATUS_SUCCESS;
6367}
6368
6369VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6370{
6371 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6372 hdd_adapter_t *pAdapter;
6373 VOS_STATUS status;
6374 v_U32_t roamId;
6375
6376 ENTER();
6377
6378 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6379
6380 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6381 {
6382 pAdapter = pAdapterNode->pAdapter;
6383
6384 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6385 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6386 {
6387 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6388 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6389
6390 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6391 init_completion(&pAdapter->disconnect_comp_var);
6392 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6393 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6394
6395 wait_for_completion_interruptible_timeout(
6396 &pAdapter->disconnect_comp_var,
6397 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6398
6399 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6400 pHddCtx->isAmpAllowed = VOS_FALSE;
6401 sme_RoamConnect(pHddCtx->hHal,
6402 pAdapter->sessionId, &(pWextState->roamProfile),
6403 &roamId);
6404 }
6405
6406 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6407 pAdapterNode = pNext;
6408 }
6409
6410 EXIT();
6411
6412 return VOS_STATUS_SUCCESS;
6413}
6414
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006415void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6416{
6417 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6418 VOS_STATUS status;
6419 hdd_adapter_t *pAdapter;
6420 hdd_station_ctx_t *pHddStaCtx;
6421 hdd_ap_ctx_t *pHddApCtx;
6422 hdd_hostapd_state_t * pHostapdState;
6423 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6424 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6425 const char *p2pMode = "DEV";
6426 const char *ccMode = "Standalone";
6427 int n;
6428
6429 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6430 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6431 {
6432 pAdapter = pAdapterNode->pAdapter;
6433 switch (pAdapter->device_mode) {
6434 case WLAN_HDD_INFRA_STATION:
6435 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6436 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6437 staChannel = pHddStaCtx->conn_info.operationChannel;
6438 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6439 }
6440 break;
6441 case WLAN_HDD_P2P_CLIENT:
6442 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6443 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6444 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6445 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6446 p2pMode = "CLI";
6447 }
6448 break;
6449 case WLAN_HDD_P2P_GO:
6450 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6451 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6452 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6453 p2pChannel = pHddApCtx->operatingChannel;
6454 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6455 }
6456 p2pMode = "GO";
6457 break;
6458 case WLAN_HDD_SOFTAP:
6459 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6460 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6461 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6462 apChannel = pHddApCtx->operatingChannel;
6463 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6464 }
6465 break;
6466 default:
6467 break;
6468 }
6469 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6470 pAdapterNode = pNext;
6471 }
6472 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6473 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6474 }
6475 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6476 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6477 if (p2pChannel > 0) {
6478 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6479 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6480 }
6481 if (apChannel > 0) {
6482 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6483 apChannel, MAC_ADDR_ARRAY(apBssid));
6484 }
6485
6486 if (p2pChannel > 0 && apChannel > 0) {
6487 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6488 }
6489}
6490
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006491bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006492{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006493 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006494}
6495
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006496/* Once SSR is disabled then it cannot be set. */
6497void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006498{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006499 if (HDD_SSR_DISABLED == isSsrRequired)
6500 return;
6501
Jeff Johnson295189b2012-06-20 16:38:30 -07006502 isSsrRequired = value;
6503}
6504
6505VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6506 hdd_adapter_list_node_t** ppAdapterNode)
6507{
6508 VOS_STATUS status;
6509 spin_lock(&pHddCtx->hddAdapters.lock);
6510 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6511 (hdd_list_node_t**) ppAdapterNode );
6512 spin_unlock(&pHddCtx->hddAdapters.lock);
6513 return status;
6514}
6515
6516VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6517 hdd_adapter_list_node_t* pAdapterNode,
6518 hdd_adapter_list_node_t** pNextAdapterNode)
6519{
6520 VOS_STATUS status;
6521 spin_lock(&pHddCtx->hddAdapters.lock);
6522 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6523 (hdd_list_node_t*) pAdapterNode,
6524 (hdd_list_node_t**)pNextAdapterNode );
6525
6526 spin_unlock(&pHddCtx->hddAdapters.lock);
6527 return status;
6528}
6529
6530VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6531 hdd_adapter_list_node_t* pAdapterNode)
6532{
6533 VOS_STATUS status;
6534 spin_lock(&pHddCtx->hddAdapters.lock);
6535 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6536 &pAdapterNode->node );
6537 spin_unlock(&pHddCtx->hddAdapters.lock);
6538 return status;
6539}
6540
6541VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6542 hdd_adapter_list_node_t** ppAdapterNode)
6543{
6544 VOS_STATUS status;
6545 spin_lock(&pHddCtx->hddAdapters.lock);
6546 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6547 (hdd_list_node_t**) ppAdapterNode );
6548 spin_unlock(&pHddCtx->hddAdapters.lock);
6549 return status;
6550}
6551
6552VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6553 hdd_adapter_list_node_t* pAdapterNode)
6554{
6555 VOS_STATUS status;
6556 spin_lock(&pHddCtx->hddAdapters.lock);
6557 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6558 (hdd_list_node_t*) pAdapterNode );
6559 spin_unlock(&pHddCtx->hddAdapters.lock);
6560 return status;
6561}
6562
6563VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6564 hdd_adapter_list_node_t* pAdapterNode)
6565{
6566 VOS_STATUS status;
6567 spin_lock(&pHddCtx->hddAdapters.lock);
6568 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6569 (hdd_list_node_t*) pAdapterNode );
6570 spin_unlock(&pHddCtx->hddAdapters.lock);
6571 return status;
6572}
6573
6574hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6575 tSirMacAddr macAddr )
6576{
6577 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6578 hdd_adapter_t *pAdapter;
6579 VOS_STATUS status;
6580
6581 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6582
6583 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6584 {
6585 pAdapter = pAdapterNode->pAdapter;
6586
6587 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6588 macAddr, sizeof(tSirMacAddr) ) )
6589 {
6590 return pAdapter;
6591 }
6592 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6593 pAdapterNode = pNext;
6594 }
6595
6596 return NULL;
6597
6598}
6599
6600hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6601{
6602 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6603 hdd_adapter_t *pAdapter;
6604 VOS_STATUS status;
6605
6606 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6607
6608 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6609 {
6610 pAdapter = pAdapterNode->pAdapter;
6611
6612 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6613 IFNAMSIZ ) )
6614 {
6615 return pAdapter;
6616 }
6617 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6618 pAdapterNode = pNext;
6619 }
6620
6621 return NULL;
6622
6623}
6624
6625hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6626{
6627 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6628 hdd_adapter_t *pAdapter;
6629 VOS_STATUS status;
6630
6631 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6632
6633 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6634 {
6635 pAdapter = pAdapterNode->pAdapter;
6636
6637 if( pAdapter && (mode == pAdapter->device_mode) )
6638 {
6639 return pAdapter;
6640 }
6641 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6642 pAdapterNode = pNext;
6643 }
6644
6645 return NULL;
6646
6647}
6648
6649//Remove this function later
6650hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6651{
6652 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6653 hdd_adapter_t *pAdapter;
6654 VOS_STATUS status;
6655
6656 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6657
6658 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6659 {
6660 pAdapter = pAdapterNode->pAdapter;
6661
6662 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6663 {
6664 return pAdapter;
6665 }
6666
6667 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6668 pAdapterNode = pNext;
6669 }
6670
6671 return NULL;
6672
6673}
6674
Jeff Johnson295189b2012-06-20 16:38:30 -07006675/**---------------------------------------------------------------------------
6676
6677 \brief hdd_set_monitor_tx_adapter() -
6678
6679 This API initializes the adapter to be used while transmitting on monitor
6680 adapter.
6681
6682 \param - pHddCtx - Pointer to the HDD context.
6683 pAdapter - Adapter that will used for TX. This can be NULL.
6684 \return - None.
6685 --------------------------------------------------------------------------*/
6686void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6687{
6688 hdd_adapter_t *pMonAdapter;
6689
6690 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6691
6692 if( NULL != pMonAdapter )
6693 {
6694 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6695 }
6696}
Jeff Johnson295189b2012-06-20 16:38:30 -07006697/**---------------------------------------------------------------------------
6698
6699 \brief hdd_select_queue() -
6700
6701 This API returns the operating channel of the requested device mode
6702
6703 \param - pHddCtx - Pointer to the HDD context.
6704 - mode - Device mode for which operating channel is required
6705 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6706 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6707 \return - channel number. "0" id the requested device is not found OR it is not connected.
6708 --------------------------------------------------------------------------*/
6709v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6710{
6711 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6712 VOS_STATUS status;
6713 hdd_adapter_t *pAdapter;
6714 v_U8_t operatingChannel = 0;
6715
6716 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6717
6718 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6719 {
6720 pAdapter = pAdapterNode->pAdapter;
6721
6722 if( mode == pAdapter->device_mode )
6723 {
6724 switch(pAdapter->device_mode)
6725 {
6726 case WLAN_HDD_INFRA_STATION:
6727 case WLAN_HDD_P2P_CLIENT:
6728 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6729 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6730 break;
6731 case WLAN_HDD_SOFTAP:
6732 case WLAN_HDD_P2P_GO:
6733 /*softap connection info */
6734 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6735 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6736 break;
6737 default:
6738 break;
6739 }
6740
6741 break; //Found the device of interest. break the loop
6742 }
6743
6744 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6745 pAdapterNode = pNext;
6746 }
6747 return operatingChannel;
6748}
6749
6750#ifdef WLAN_FEATURE_PACKET_FILTERING
6751/**---------------------------------------------------------------------------
6752
6753 \brief hdd_set_multicast_list() -
6754
6755 This used to set the multicast address list.
6756
6757 \param - dev - Pointer to the WLAN device.
6758 - skb - Pointer to OS packet (sk_buff).
6759 \return - success/fail
6760
6761 --------------------------------------------------------------------------*/
6762static void hdd_set_multicast_list(struct net_device *dev)
6763{
6764 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006765 int mc_count;
6766 int i = 0;
6767 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306768
6769 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006770 {
6771 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306772 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006773 return;
6774 }
6775
6776 if (dev->flags & IFF_ALLMULTI)
6777 {
6778 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006779 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306780 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006781 }
6782 else
6783 {
6784 mc_count = netdev_mc_count(dev);
6785 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006786 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006787 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6788 {
6789 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006790 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306791 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006792 return;
6793 }
6794
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306795 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006796
6797 netdev_for_each_mc_addr(ha, dev) {
6798 if (i == mc_count)
6799 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306800 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6801 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08006802 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006803 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306804 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006805 i++;
6806 }
6807 }
6808 return;
6809}
6810#endif
6811
6812/**---------------------------------------------------------------------------
6813
6814 \brief hdd_select_queue() -
6815
6816 This function is registered with the Linux OS for network
6817 core to decide which queue to use first.
6818
6819 \param - dev - Pointer to the WLAN device.
6820 - skb - Pointer to OS packet (sk_buff).
6821 \return - ac, Queue Index/access category corresponding to UP in IP header
6822
6823 --------------------------------------------------------------------------*/
6824v_U16_t hdd_select_queue(struct net_device *dev,
6825 struct sk_buff *skb)
6826{
6827 return hdd_wmm_select_queue(dev, skb);
6828}
6829
6830
6831/**---------------------------------------------------------------------------
6832
6833 \brief hdd_wlan_initial_scan() -
6834
6835 This function triggers the initial scan
6836
6837 \param - pAdapter - Pointer to the HDD adapter.
6838
6839 --------------------------------------------------------------------------*/
6840void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6841{
6842 tCsrScanRequest scanReq;
6843 tCsrChannelInfo channelInfo;
6844 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006845 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006846 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6847
6848 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6849 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6850 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6851
6852 if(sme_Is11dSupported(pHddCtx->hHal))
6853 {
6854 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6855 if ( HAL_STATUS_SUCCESS( halStatus ) )
6856 {
6857 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6858 if( !scanReq.ChannelInfo.ChannelList )
6859 {
6860 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6861 vos_mem_free(channelInfo.ChannelList);
6862 return;
6863 }
6864 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6865 channelInfo.numOfChannels);
6866 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6867 vos_mem_free(channelInfo.ChannelList);
6868 }
6869
6870 scanReq.scanType = eSIR_PASSIVE_SCAN;
6871 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6872 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6873 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6874 }
6875 else
6876 {
6877 scanReq.scanType = eSIR_ACTIVE_SCAN;
6878 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6879 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6880 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6881 }
6882
6883 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6884 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6885 {
6886 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6887 __func__, halStatus );
6888 }
6889
6890 if(sme_Is11dSupported(pHddCtx->hHal))
6891 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6892}
6893
6894struct fullPowerContext
6895{
6896 struct completion completion;
6897 unsigned int magic;
6898};
6899#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6900
6901/**---------------------------------------------------------------------------
6902
6903 \brief hdd_full_power_callback() - HDD full power callback function
6904
6905 This is the function invoked by SME to inform the result of a full power
6906 request issued by HDD
6907
6908 \param - callbackcontext - Pointer to cookie
6909 \param - status - result of request
6910
6911 \return - None
6912
6913 --------------------------------------------------------------------------*/
6914static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6915{
6916 struct fullPowerContext *pContext = callbackContext;
6917
6918 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306919 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006920
6921 if (NULL == callbackContext)
6922 {
6923 hddLog(VOS_TRACE_LEVEL_ERROR,
6924 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006925 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006926 return;
6927 }
6928
6929 /* there is a race condition that exists between this callback function
6930 and the caller since the caller could time out either before or
6931 while this code is executing. we'll assume the timeout hasn't
6932 occurred, but we'll verify that right before we save our work */
6933
6934 if (POWER_CONTEXT_MAGIC != pContext->magic)
6935 {
6936 /* the caller presumably timed out so there is nothing we can do */
6937 hddLog(VOS_TRACE_LEVEL_WARN,
6938 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006939 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006940 return;
6941 }
6942
6943 /* the race is on. caller could have timed out immediately after
6944 we verified the magic, but if so, caller will wait a short time
6945 for us to notify the caller, so the context will stay valid */
6946 complete(&pContext->completion);
6947}
6948
6949/**---------------------------------------------------------------------------
6950
6951 \brief hdd_wlan_exit() - HDD WLAN exit function
6952
6953 This is the driver exit point (invoked during rmmod)
6954
6955 \param - pHddCtx - Pointer to the HDD Context
6956
6957 \return - None
6958
6959 --------------------------------------------------------------------------*/
6960void hdd_wlan_exit(hdd_context_t *pHddCtx)
6961{
6962 eHalStatus halStatus;
6963 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6964 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306965 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006966 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006967 struct fullPowerContext powerContext;
6968 long lrc;
6969
6970 ENTER();
6971
Jeff Johnson88ba7742013-02-27 14:36:02 -08006972 if (VOS_FTM_MODE != hdd_get_conparam())
6973 {
6974 // Unloading, restart logic is no more required.
6975 wlan_hdd_restart_deinit(pHddCtx);
6976 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006977
Jeff Johnson295189b2012-06-20 16:38:30 -07006978 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006979 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006980 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006981 {
6982 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6983 WLAN_HDD_INFRA_STATION);
6984 if (pAdapter == NULL)
6985 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6986
6987 if (pAdapter != NULL)
6988 {
6989 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6990 hdd_UnregisterWext(pAdapter->dev);
6991 }
6992 }
6993 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006994
Jeff Johnson295189b2012-06-20 16:38:30 -07006995 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006996 {
6997 wlan_hdd_ftm_close(pHddCtx);
6998 goto free_hdd_ctx;
6999 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007000 //Stop the Interface TX queue.
7001 //netif_tx_disable(pWlanDev);
7002 //netif_carrier_off(pWlanDev);
7003
Jeff Johnson295189b2012-06-20 16:38:30 -07007004 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7005 {
7006 pAdapter = hdd_get_adapter(pHddCtx,
7007 WLAN_HDD_SOFTAP);
7008 }
7009 else
7010 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007011 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007012 {
7013 pAdapter = hdd_get_adapter(pHddCtx,
7014 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007015 if (pAdapter == NULL)
7016 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007017 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007018 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007019 /* DeRegister with platform driver as client for Suspend/Resume */
7020 vosStatus = hddDeregisterPmOps(pHddCtx);
7021 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7022 {
7023 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7024 VOS_ASSERT(0);
7025 }
7026
7027 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7028 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7029 {
7030 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7031 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007032
7033 // Cancel any outstanding scan requests. We are about to close all
7034 // of our adapters, but an adapter structure is what SME passes back
7035 // to our callback function. Hence if there are any outstanding scan
7036 // requests then there is a race condition between when the adapter
7037 // is closed and when the callback is invoked. We try to resolve that
7038 // race condition here by canceling any outstanding scans before we
7039 // close the adapters.
7040 // Note that the scans may be cancelled in an asynchronous manner, so
7041 // ideally there needs to be some kind of synchronization. Rather than
7042 // introduce a new synchronization here, we will utilize the fact that
7043 // we are about to Request Full Power, and since that is synchronized,
7044 // the expectation is that by the time Request Full Power has completed,
7045 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007046 if (NULL != pAdapter)
7047 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7048 else
7049 hddLog(VOS_TRACE_LEVEL_ERROR,
7050 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007051
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007052 //Stop the traffic monitor timer
7053 if ( VOS_TIMER_STATE_RUNNING ==
7054 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7055 {
7056 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7057 }
7058
7059 // Destroy the traffic monitor timer
7060 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7061 &pHddCtx->tx_rx_trafficTmr)))
7062 {
7063 hddLog(VOS_TRACE_LEVEL_ERROR,
7064 "%s: Cannot deallocate Traffic monitor timer", __func__);
7065 }
7066
Jeff Johnson295189b2012-06-20 16:38:30 -07007067 //Disable IMPS/BMPS as we do not want the device to enter any power
7068 //save mode during shutdown
7069 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7070 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7071 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7072
7073 //Ensure that device is in full power as we will touch H/W during vos_Stop
7074 init_completion(&powerContext.completion);
7075 powerContext.magic = POWER_CONTEXT_MAGIC;
7076
7077 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7078 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7079
7080 if (eHAL_STATUS_SUCCESS != halStatus)
7081 {
7082 if (eHAL_STATUS_PMC_PENDING == halStatus)
7083 {
7084 /* request was sent -- wait for the response */
7085 lrc = wait_for_completion_interruptible_timeout(
7086 &powerContext.completion,
7087 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
7088 /* either we have a response or we timed out
7089 either way, first invalidate our magic */
7090 powerContext.magic = 0;
7091 if (lrc <= 0)
7092 {
7093 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007094 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007095 /* there is a race condition such that the callback
7096 function could be executing at the same time we are. of
7097 primary concern is if the callback function had already
7098 verified the "magic" but hasn't yet set the completion
7099 variable. Since the completion variable is on our
7100 stack, we'll delay just a bit to make sure the data is
7101 still valid if that is the case */
7102 msleep(50);
7103 }
7104 }
7105 else
7106 {
7107 hddLog(VOS_TRACE_LEVEL_ERROR,
7108 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007109 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007110 VOS_ASSERT(0);
7111 /* continue -- need to clean up as much as possible */
7112 }
7113 }
7114
Yue Ma0d4891e2013-08-06 17:01:45 -07007115 hdd_debugfs_exit(pHddCtx);
7116
Jeff Johnson295189b2012-06-20 16:38:30 -07007117 // Unregister the Net Device Notifier
7118 unregister_netdevice_notifier(&hdd_netdev_notifier);
7119
Jeff Johnson295189b2012-06-20 16:38:30 -07007120 hdd_stop_all_adapters( pHddCtx );
7121
Jeff Johnson295189b2012-06-20 16:38:30 -07007122#ifdef WLAN_BTAMP_FEATURE
7123 vosStatus = WLANBAP_Stop(pVosContext);
7124 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7125 {
7126 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7127 "%s: Failed to stop BAP",__func__);
7128 }
7129#endif //WLAN_BTAMP_FEATURE
7130
7131 //Stop all the modules
7132 vosStatus = vos_stop( pVosContext );
7133 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7134 {
7135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7136 "%s: Failed to stop VOSS",__func__);
7137 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7138 }
7139
Jeff Johnson295189b2012-06-20 16:38:30 -07007140 //Assert Deep sleep signal now to put Libra HW in lowest power state
7141 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7142 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7143
7144 //Vote off any PMIC voltage supplies
7145 vos_chipPowerDown(NULL, NULL, NULL);
7146
7147 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7148
Leo Chang59cdc7e2013-07-10 10:08:21 -07007149
Jeff Johnson295189b2012-06-20 16:38:30 -07007150 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007151 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007152
7153 //Close the scheduler before calling vos_close to make sure no thread is
7154 // scheduled after the each module close is called i.e after all the data
7155 // structures are freed.
7156 vosStatus = vos_sched_close( pVosContext );
7157 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7158 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7159 "%s: Failed to close VOSS Scheduler",__func__);
7160 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7161 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007162#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007163#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7164 /* Destroy the wake lock */
7165 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7166#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007167 /* Destroy the wake lock */
7168 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007169#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007170
7171 //Close VOSS
7172 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7173 vos_close(pVosContext);
7174
Jeff Johnson295189b2012-06-20 16:38:30 -07007175 //Close Watchdog
7176 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7177 vos_watchdog_close(pVosContext);
7178
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307179 //Clean up HDD Nlink Service
7180 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007181#ifdef WLAN_KD_READY_NOTIFIER
7182 nl_srv_exit(pHddCtx->ptt_pid);
7183#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307184 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007185#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307186
Jeff Johnson295189b2012-06-20 16:38:30 -07007187 /* Cancel the vote for XO Core ON.
7188 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7189 * exited at this point
7190 */
7191 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007192 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007193 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7194 {
7195 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7196 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007197 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007198 }
7199
7200 hdd_close_all_adapters( pHddCtx );
7201
7202
7203 //Free up dynamically allocated members inside HDD Adapter
7204 kfree(pHddCtx->cfg_ini);
7205 pHddCtx->cfg_ini= NULL;
7206
7207 /* free the power on lock from platform driver */
7208 if (free_riva_power_on_lock("wlan"))
7209 {
7210 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7211 __func__);
7212 }
7213
Jeff Johnson88ba7742013-02-27 14:36:02 -08007214free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007215 /* FTM mode, WIPHY did not registered
7216 If un-register here, system crash will happen */
7217 if (VOS_FTM_MODE != hdd_get_conparam())
7218 {
7219 wiphy_unregister(wiphy) ;
7220 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007221 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007222 if (hdd_is_ssr_required())
7223 {
7224 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007225 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007226 msleep(5000);
7227 }
7228 hdd_set_ssr_required (VOS_FALSE);
7229}
7230
7231
7232/**---------------------------------------------------------------------------
7233
7234 \brief hdd_update_config_from_nv() - Function to update the contents of
7235 the running configuration with parameters taken from NV storage
7236
7237 \param - pHddCtx - Pointer to the HDD global context
7238
7239 \return - VOS_STATUS_SUCCESS if successful
7240
7241 --------------------------------------------------------------------------*/
7242static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7243{
Jeff Johnson295189b2012-06-20 16:38:30 -07007244 v_BOOL_t itemIsValid = VOS_FALSE;
7245 VOS_STATUS status;
7246 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7247 v_U8_t macLoop;
7248
7249 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7250 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7251 if(status != VOS_STATUS_SUCCESS)
7252 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007253 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007254 return VOS_STATUS_E_FAILURE;
7255 }
7256
7257 if (itemIsValid == VOS_TRUE)
7258 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007259 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007260 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7261 VOS_MAX_CONCURRENCY_PERSONA);
7262 if(status != VOS_STATUS_SUCCESS)
7263 {
7264 /* Get MAC from NV fail, not update CFG info
7265 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007266 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007267 return VOS_STATUS_E_FAILURE;
7268 }
7269
7270 /* If first MAC is not valid, treat all others are not valid
7271 * Then all MACs will be got from ini file */
7272 if(vos_is_macaddr_zero(&macFromNV[0]))
7273 {
7274 /* MAC address in NV file is not configured yet */
7275 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7276 return VOS_STATUS_E_INVAL;
7277 }
7278
7279 /* Get MAC address from NV, update CFG info */
7280 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7281 {
7282 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7283 {
7284 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7285 /* This MAC is not valid, skip it
7286 * This MAC will be got from ini file */
7287 }
7288 else
7289 {
7290 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7291 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7292 VOS_MAC_ADDR_SIZE);
7293 }
7294 }
7295 }
7296 else
7297 {
7298 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7299 return VOS_STATUS_E_FAILURE;
7300 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007301
Jeff Johnson295189b2012-06-20 16:38:30 -07007302
7303 return VOS_STATUS_SUCCESS;
7304}
7305
7306/**---------------------------------------------------------------------------
7307
7308 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7309
7310 \param - pAdapter - Pointer to the HDD
7311
7312 \return - None
7313
7314 --------------------------------------------------------------------------*/
7315VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7316{
7317 eHalStatus halStatus;
7318 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307319 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007320
Jeff Johnson295189b2012-06-20 16:38:30 -07007321
7322 // Send ready indication to the HDD. This will kick off the MAC
7323 // into a 'running' state and should kick off an initial scan.
7324 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7325 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7326 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307327 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007328 "code %08d [x%08x]",__func__, halStatus, halStatus );
7329 return VOS_STATUS_E_FAILURE;
7330 }
7331
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307332 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007333 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7334 // And RIVA will crash
7335 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7336 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307337 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7338 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7339
7340
Jeff Johnson295189b2012-06-20 16:38:30 -07007341 return VOS_STATUS_SUCCESS;
7342}
7343
Jeff Johnson295189b2012-06-20 16:38:30 -07007344/* wake lock APIs for HDD */
7345void hdd_prevent_suspend(void)
7346{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007347#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007348 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007349#else
7350 wcnss_prevent_suspend();
7351#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007352}
7353
7354void hdd_allow_suspend(void)
7355{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007356#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007357 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007358#else
7359 wcnss_allow_suspend();
7360#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007361}
7362
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007363void hdd_allow_suspend_timeout(v_U32_t timeout)
7364{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007365#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007366 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007367#else
7368 /* Do nothing as there is no API in wcnss for timeout*/
7369#endif
7370}
7371
Jeff Johnson295189b2012-06-20 16:38:30 -07007372/**---------------------------------------------------------------------------
7373
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007374 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7375 information between Host and Riva
7376
7377 This function gets reported version of FW
7378 It also finds the version of Riva headers used to compile the host
7379 It compares the above two and prints a warning if they are different
7380 It gets the SW and HW version string
7381 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7382 indicating the features they support through a bitmap
7383
7384 \param - pHddCtx - Pointer to HDD context
7385
7386 \return - void
7387
7388 --------------------------------------------------------------------------*/
7389
7390void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7391{
7392
7393 tSirVersionType versionCompiled;
7394 tSirVersionType versionReported;
7395 tSirVersionString versionString;
7396 tANI_U8 fwFeatCapsMsgSupported = 0;
7397 VOS_STATUS vstatus;
7398
7399 /* retrieve and display WCNSS version information */
7400 do {
7401
7402 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7403 &versionCompiled);
7404 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7405 {
7406 hddLog(VOS_TRACE_LEVEL_FATAL,
7407 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007408 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007409 break;
7410 }
7411
7412 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7413 &versionReported);
7414 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7415 {
7416 hddLog(VOS_TRACE_LEVEL_FATAL,
7417 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007418 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007419 break;
7420 }
7421
7422 if ((versionCompiled.major != versionReported.major) ||
7423 (versionCompiled.minor != versionReported.minor) ||
7424 (versionCompiled.version != versionReported.version) ||
7425 (versionCompiled.revision != versionReported.revision))
7426 {
7427 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7428 "Host expected %u.%u.%u.%u\n",
7429 WLAN_MODULE_NAME,
7430 (int)versionReported.major,
7431 (int)versionReported.minor,
7432 (int)versionReported.version,
7433 (int)versionReported.revision,
7434 (int)versionCompiled.major,
7435 (int)versionCompiled.minor,
7436 (int)versionCompiled.version,
7437 (int)versionCompiled.revision);
7438 }
7439 else
7440 {
7441 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7442 WLAN_MODULE_NAME,
7443 (int)versionReported.major,
7444 (int)versionReported.minor,
7445 (int)versionReported.version,
7446 (int)versionReported.revision);
7447 }
7448
7449 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7450 versionString,
7451 sizeof(versionString));
7452 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7453 {
7454 hddLog(VOS_TRACE_LEVEL_FATAL,
7455 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007456 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007457 break;
7458 }
7459
7460 pr_info("%s: WCNSS software version %s\n",
7461 WLAN_MODULE_NAME, versionString);
7462
7463 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7464 versionString,
7465 sizeof(versionString));
7466 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7467 {
7468 hddLog(VOS_TRACE_LEVEL_FATAL,
7469 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007470 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007471 break;
7472 }
7473
7474 pr_info("%s: WCNSS hardware version %s\n",
7475 WLAN_MODULE_NAME, versionString);
7476
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007477 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7478 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007479 send the message only if it the riva is 1.1
7480 minor numbers for different riva branches:
7481 0 -> (1.0)Mainline Build
7482 1 -> (1.1)Mainline Build
7483 2->(1.04) Stability Build
7484 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007485 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007486 ((versionReported.minor>=1) && (versionReported.version>=1)))
7487 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7488 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007489
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007490 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007491 {
7492#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7493 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7494 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7495#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007496 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7497 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7498 {
7499 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7500 }
7501
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007502 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007503 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007504
7505 } while (0);
7506
7507}
7508
7509/**---------------------------------------------------------------------------
7510
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307511 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7512
7513 \param - pHddCtx - Pointer to the hdd context
7514
7515 \return - true if hardware supports 5GHz
7516
7517 --------------------------------------------------------------------------*/
7518static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7519{
7520 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7521 * then hardware support 5Ghz.
7522 */
7523 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7524 {
7525 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7526 return true;
7527 }
7528 else
7529 {
7530 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7531 __func__);
7532 return false;
7533 }
7534}
7535
7536
7537/**---------------------------------------------------------------------------
7538
Jeff Johnson295189b2012-06-20 16:38:30 -07007539 \brief hdd_wlan_startup() - HDD init function
7540
7541 This is the driver startup code executed once a WLAN device has been detected
7542
7543 \param - dev - Pointer to the underlying device
7544
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007545 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007546
7547 --------------------------------------------------------------------------*/
7548
7549int hdd_wlan_startup(struct device *dev )
7550{
7551 VOS_STATUS status;
7552 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007553 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007554 hdd_context_t *pHddCtx = NULL;
7555 v_CONTEXT_t pVosContext= NULL;
7556#ifdef WLAN_BTAMP_FEATURE
7557 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7558 WLANBAP_ConfigType btAmpConfig;
7559 hdd_config_t *pConfig;
7560#endif
7561 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007562 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007563
7564 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007565 /*
7566 * cfg80211: wiphy allocation
7567 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307568 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007569
7570 if(wiphy == NULL)
7571 {
7572 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007573 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007574 }
7575
7576 pHddCtx = wiphy_priv(wiphy);
7577
Jeff Johnson295189b2012-06-20 16:38:30 -07007578 //Initialize the adapter context to zeros.
7579 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7580
Jeff Johnson295189b2012-06-20 16:38:30 -07007581 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007582 hdd_prevent_suspend();
7583 pHddCtx->isLoadUnloadInProgress = TRUE;
7584
7585 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7586
7587 /*Get vos context here bcoz vos_open requires it*/
7588 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7589
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007590 if(pVosContext == NULL)
7591 {
7592 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7593 goto err_free_hdd_context;
7594 }
7595
Jeff Johnson295189b2012-06-20 16:38:30 -07007596 //Save the Global VOSS context in adapter context for future.
7597 pHddCtx->pvosContext = pVosContext;
7598
7599 //Save the adapter context in global context for future.
7600 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7601
Jeff Johnson295189b2012-06-20 16:38:30 -07007602 pHddCtx->parent_dev = dev;
7603
7604 init_completion(&pHddCtx->full_pwr_comp_var);
7605 init_completion(&pHddCtx->standby_comp_var);
7606 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007607 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007608 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307609 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007610
7611#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007612 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007613#else
7614 init_completion(&pHddCtx->driver_crda_req);
7615#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007616
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307617 spin_lock_init(&pHddCtx->schedScan_lock);
7618
Jeff Johnson295189b2012-06-20 16:38:30 -07007619 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7620
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307621#ifdef FEATURE_WLAN_TDLS
7622 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7623 * invoked by other instances also) to protect the concurrent
7624 * access for the Adapters by TDLS module.
7625 */
7626 mutex_init(&pHddCtx->tdls_lock);
7627#endif
7628
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307629 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007630 // Load all config first as TL config is needed during vos_open
7631 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7632 if(pHddCtx->cfg_ini == NULL)
7633 {
7634 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7635 goto err_free_hdd_context;
7636 }
7637
7638 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7639
7640 // Read and parse the qcom_cfg.ini file
7641 status = hdd_parse_config_ini( pHddCtx );
7642 if ( VOS_STATUS_SUCCESS != status )
7643 {
7644 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7645 __func__, WLAN_INI_FILE);
7646 goto err_config;
7647 }
7648
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307649 /* INI has been read, initialise the configuredMcastBcastFilter with
7650 * INI value as this will serve as the default value
7651 */
7652 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7653 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7654 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307655
7656 if (false == hdd_is_5g_supported(pHddCtx))
7657 {
7658 //5Ghz is not supported.
7659 if (1 != pHddCtx->cfg_ini->nBandCapability)
7660 {
7661 hddLog(VOS_TRACE_LEVEL_INFO,
7662 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7663 pHddCtx->cfg_ini->nBandCapability = 1;
7664 }
7665 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307666
7667 /* If SNR Monitoring is enabled, FW has to parse all beacons
7668 * for calcaluting and storing the average SNR, so set Nth beacon
7669 * filter to 1 to enable FW to parse all the beaocons
7670 */
7671 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7672 {
7673 /* The log level is deliberately set to WARN as overriding
7674 * nthBeaconFilter to 1 will increase power cosumption and this
7675 * might just prove helpful to detect the power issue.
7676 */
7677 hddLog(VOS_TRACE_LEVEL_WARN,
7678 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7679 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7680 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007681 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307682 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007683 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307684 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007685 {
7686 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307687 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7688 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007689 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007690
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007691 // Update VOS trace levels based upon the cfg.ini
7692 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7693 pHddCtx->cfg_ini->vosTraceEnableBAP);
7694 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7695 pHddCtx->cfg_ini->vosTraceEnableTL);
7696 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7697 pHddCtx->cfg_ini->vosTraceEnableWDI);
7698 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7699 pHddCtx->cfg_ini->vosTraceEnableHDD);
7700 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7701 pHddCtx->cfg_ini->vosTraceEnableSME);
7702 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7703 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307704 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7705 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007706 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7707 pHddCtx->cfg_ini->vosTraceEnableWDA);
7708 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7709 pHddCtx->cfg_ini->vosTraceEnableSYS);
7710 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7711 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007712 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7713 pHddCtx->cfg_ini->vosTraceEnableSAP);
7714 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7715 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007716
Jeff Johnson295189b2012-06-20 16:38:30 -07007717 // Update WDI trace levels based upon the cfg.ini
7718 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7719 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7720 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7721 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7722 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7723 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7724 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7725 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007726
Jeff Johnson88ba7742013-02-27 14:36:02 -08007727 if (VOS_FTM_MODE == hdd_get_conparam())
7728 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007729 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7730 {
7731 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7732 goto err_free_hdd_context;
7733 }
7734 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7735 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007736 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007737
Jeff Johnson88ba7742013-02-27 14:36:02 -08007738 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007739 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7740 {
7741 status = vos_watchdog_open(pVosContext,
7742 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7743
7744 if(!VOS_IS_STATUS_SUCCESS( status ))
7745 {
7746 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307747 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007748 }
7749 }
7750
7751 pHddCtx->isLogpInProgress = FALSE;
7752 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7753
Jeff Johnson295189b2012-06-20 16:38:30 -07007754 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7755 if(!VOS_IS_STATUS_SUCCESS(status))
7756 {
7757 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007758 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007759 }
7760
Amar Singhala49cbc52013-10-08 18:37:44 -07007761#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007762 /* initialize the NV module. This is required so that
7763 we can initialize the channel information in wiphy
7764 from the NV.bin data. The channel information in
7765 wiphy needs to be initialized before wiphy registration */
7766
7767 status = vos_nv_open();
7768 if (!VOS_IS_STATUS_SUCCESS(status))
7769 {
7770 /* NV module cannot be initialized */
7771 hddLog( VOS_TRACE_LEVEL_FATAL,
7772 "%s: vos_nv_open failed", __func__);
7773 goto err_clkvote;
7774 }
7775
7776 status = vos_init_wiphy_from_nv_bin();
7777 if (!VOS_IS_STATUS_SUCCESS(status))
7778 {
7779 /* NV module cannot be initialized */
7780 hddLog( VOS_TRACE_LEVEL_FATAL,
7781 "%s: vos_init_wiphy failed", __func__);
7782 goto err_vos_nv_close;
7783 }
7784
Amar Singhala49cbc52013-10-08 18:37:44 -07007785 /* registration of wiphy dev with cfg80211 */
7786 if (0 > wlan_hdd_cfg80211_register(wiphy))
7787 {
7788 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007789 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007790 }
7791#endif
7792
Jeff Johnson295189b2012-06-20 16:38:30 -07007793 status = vos_open( &pVosContext, 0);
7794 if ( !VOS_IS_STATUS_SUCCESS( status ))
7795 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007796 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007797 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007798 }
7799
Jeff Johnson295189b2012-06-20 16:38:30 -07007800 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7801
7802 if ( NULL == pHddCtx->hHal )
7803 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007804 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007805 goto err_vosclose;
7806 }
7807
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007808 status = vos_preStart( pHddCtx->pvosContext );
7809 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7810 {
7811 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7812 goto err_vosclose;
7813 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007814
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007815 /* Note that the vos_preStart() sequence triggers the cfg download.
7816 The cfg download must occur before we update the SME config
7817 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007818 status = hdd_set_sme_config( pHddCtx );
7819
7820 if ( VOS_STATUS_SUCCESS != status )
7821 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007822 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7823 goto err_vosclose;
7824 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007825
7826 //Initialize the WMM module
7827 status = hdd_wmm_init(pHddCtx);
7828 if (!VOS_IS_STATUS_SUCCESS(status))
7829 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007830 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007831 goto err_vosclose;
7832 }
7833
Jeff Johnson295189b2012-06-20 16:38:30 -07007834 /* In the integrated architecture we update the configuration from
7835 the INI file and from NV before vOSS has been started so that
7836 the final contents are available to send down to the cCPU */
7837
Arif Hussain66559122013-11-21 10:11:40 -08007838 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
7839 {
7840 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
7841 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
7842 __func__, enable_dfs_chan_scan);
7843 }
7844 if (0 == enable_11d || 1 == enable_11d)
7845 {
7846 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
7847 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
7848 __func__, enable_11d);
7849 }
7850
Jeff Johnson295189b2012-06-20 16:38:30 -07007851 // Apply the cfg.ini to cfg.dat
7852 if (FALSE == hdd_update_config_dat(pHddCtx))
7853 {
7854 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7855 goto err_vosclose;
7856 }
7857
7858 // Apply the NV to cfg.dat
7859 /* Prima Update MAC address only at here */
7860 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7861 {
7862#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7863 /* There was not a valid set of MAC Addresses in NV. See if the
7864 default addresses were modified by the cfg.ini settings. If so,
7865 we'll use them, but if not, we'll autogenerate a set of MAC
7866 addresses based upon the device serial number */
7867
7868 static const v_MACADDR_t default_address =
7869 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7870 unsigned int serialno;
7871 int i;
7872
7873 serialno = wcnss_get_serial_number();
7874 if ((0 != serialno) &&
7875 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7876 sizeof(default_address))))
7877 {
7878 /* cfg.ini has the default address, invoke autogen logic */
7879
7880 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7881 bytes of the serial number that can be used to generate
7882 the other 3 bytes of the MAC address. Mask off all but
7883 the lower 3 bytes (this will also make sure we don't
7884 overflow in the next step) */
7885 serialno &= 0x00FFFFFF;
7886
7887 /* we need a unique address for each session */
7888 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7889
7890 /* autogen all addresses */
7891 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7892 {
7893 /* start with the entire default address */
7894 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7895 /* then replace the lower 3 bytes */
7896 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7897 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7898 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7899
7900 serialno++;
7901 }
7902
7903 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7904 MAC_ADDRESS_STR,
7905 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7906 }
7907 else
7908#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7909 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007910 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007911 "%s: Invalid MAC address in NV, using MAC from ini file "
7912 MAC_ADDRESS_STR, __func__,
7913 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7914 }
7915 }
7916 {
7917 eHalStatus halStatus;
7918 // Set the MAC Address
7919 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7920 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7921 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7922 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7923
7924 if (!HAL_STATUS_SUCCESS( halStatus ))
7925 {
7926 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7927 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007928 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007929 }
7930 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007931
7932 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7933 Note: Firmware image will be read and downloaded inside vos_start API */
7934 status = vos_start( pHddCtx->pvosContext );
7935 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7936 {
7937 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7938 goto err_vosclose;
7939 }
7940
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007941 /* Exchange capability info between Host and FW and also get versioning info from FW */
7942 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007943
7944 status = hdd_post_voss_start_config( pHddCtx );
7945 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7946 {
7947 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7948 __func__);
7949 goto err_vosstop;
7950 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007951
7952#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307953 wlan_hdd_cfg80211_update_reg_info( wiphy );
7954
7955 /* registration of wiphy dev with cfg80211 */
7956 if (0 > wlan_hdd_cfg80211_register(wiphy))
7957 {
7958 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7959 goto err_vosstop;
7960 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007961#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007962
Jeff Johnson295189b2012-06-20 16:38:30 -07007963 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7964 {
7965 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7966 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7967 }
7968 else
7969 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007970 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7971 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7972 if (pAdapter != NULL)
7973 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307974 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007975 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307976 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7977 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7978 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007979
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307980 /* Generate the P2P Device Address. This consists of the device's
7981 * primary MAC address with the locally administered bit set.
7982 */
7983 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007984 }
7985 else
7986 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307987 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7988 if (p2p_dev_addr != NULL)
7989 {
7990 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7991 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7992 }
7993 else
7994 {
7995 hddLog(VOS_TRACE_LEVEL_FATAL,
7996 "%s: Failed to allocate mac_address for p2p_device",
7997 __func__);
7998 goto err_close_adapter;
7999 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008000 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008001
8002 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8003 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8004 if ( NULL == pP2pAdapter )
8005 {
8006 hddLog(VOS_TRACE_LEVEL_FATAL,
8007 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008008 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008009 goto err_close_adapter;
8010 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008011 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008012 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008013
8014 if( pAdapter == NULL )
8015 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008016 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8017 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008018 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008019
Arif Hussain66559122013-11-21 10:11:40 -08008020 if (country_code)
8021 {
8022 eHalStatus ret;
8023 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8024#ifndef CONFIG_ENABLE_LINUX_REG
8025 hdd_checkandupdate_phymode(pAdapter, country_code);
8026#endif
8027 ret = sme_ChangeCountryCode(pHddCtx->hHal, NULL,
8028 country_code,
8029 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308030 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008031 if (eHAL_STATUS_SUCCESS == ret)
8032 {
8033 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8034 "%s: SME Change Country code from module param fail ret=%d",
8035 __func__, ret);
8036 }
8037 else
8038 {
8039 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module country code set to %c%c",
8040 __func__, country_code[0], country_code[1]);
8041 }
8042 }
8043
Jeff Johnson295189b2012-06-20 16:38:30 -07008044#ifdef WLAN_BTAMP_FEATURE
8045 vStatus = WLANBAP_Open(pVosContext);
8046 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8047 {
8048 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8049 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008050 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008051 }
8052
8053 vStatus = BSL_Init(pVosContext);
8054 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8055 {
8056 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8057 "%s: Failed to Init BSL",__func__);
8058 goto err_bap_close;
8059 }
8060 vStatus = WLANBAP_Start(pVosContext);
8061 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8062 {
8063 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8064 "%s: Failed to start TL",__func__);
8065 goto err_bap_close;
8066 }
8067
8068 pConfig = pHddCtx->cfg_ini;
8069 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8070 status = WLANBAP_SetConfig(&btAmpConfig);
8071
8072#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008073
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008074#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8075 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8076 {
8077 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8078 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8079 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8080 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8081 }
8082#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008083#ifdef FEATURE_WLAN_SCAN_PNO
8084 /*SME must send channel update configuration to RIVA*/
8085 sme_UpdateChannelConfig(pHddCtx->hHal);
8086#endif
8087
Jeff Johnson295189b2012-06-20 16:38:30 -07008088 /* Register with platform driver as client for Suspend/Resume */
8089 status = hddRegisterPmOps(pHddCtx);
8090 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8091 {
8092 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8093#ifdef WLAN_BTAMP_FEATURE
8094 goto err_bap_stop;
8095#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008096 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008097#endif //WLAN_BTAMP_FEATURE
8098 }
8099
Yue Ma0d4891e2013-08-06 17:01:45 -07008100 /* Open debugfs interface */
8101 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8102 {
8103 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8104 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008105 }
8106
Jeff Johnson295189b2012-06-20 16:38:30 -07008107 /* Register TM level change handler function to the platform */
8108 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8109 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8110 {
8111 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8112 goto err_unregister_pmops;
8113 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008114
8115 /* register for riva power on lock to platform driver */
8116 if (req_riva_power_on_lock("wlan"))
8117 {
8118 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8119 __func__);
8120 goto err_unregister_pmops;
8121 }
8122
Jeff Johnson295189b2012-06-20 16:38:30 -07008123 // register net device notifier for device change notification
8124 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8125
8126 if(ret < 0)
8127 {
8128 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8129 goto err_free_power_on_lock;
8130 }
8131
8132 //Initialize the nlink service
8133 if(nl_srv_init() != 0)
8134 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308135 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008136 goto err_reg_netdev;
8137 }
8138
Leo Chang4ce1cc52013-10-21 18:27:15 -07008139#ifdef WLAN_KD_READY_NOTIFIER
8140 pHddCtx->kd_nl_init = 1;
8141#endif /* WLAN_KD_READY_NOTIFIER */
8142
Jeff Johnson295189b2012-06-20 16:38:30 -07008143 //Initialize the BTC service
8144 if(btc_activate_service(pHddCtx) != 0)
8145 {
8146 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8147 goto err_nl_srv;
8148 }
8149
8150#ifdef PTT_SOCK_SVC_ENABLE
8151 //Initialize the PTT service
8152 if(ptt_sock_activate_svc(pHddCtx) != 0)
8153 {
8154 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8155 goto err_nl_srv;
8156 }
8157#endif
8158
Jeff Johnson295189b2012-06-20 16:38:30 -07008159 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008160 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008161 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008162 /* Action frame registered in one adapter which will
8163 * applicable to all interfaces
8164 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008165 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008166 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008167
8168 mutex_init(&pHddCtx->sap_lock);
8169
8170 pHddCtx->isLoadUnloadInProgress = FALSE;
8171
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008172#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008173#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8174 /* Initialize the wake lcok */
8175 wake_lock_init(&pHddCtx->rx_wake_lock,
8176 WAKE_LOCK_SUSPEND,
8177 "qcom_rx_wakelock");
8178#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008179 /* Initialize the wake lcok */
8180 wake_lock_init(&pHddCtx->sap_wake_lock,
8181 WAKE_LOCK_SUSPEND,
8182 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008183#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008184
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008185 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8186 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008187
8188 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8189 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308190#ifndef CONFIG_ENABLE_LINUX_REG
8191 /*updating wiphy so that regulatory user hints can be processed*/
8192 if (wiphy)
8193 {
8194 regulatory_hint(wiphy, "00");
8195 }
8196#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008197 // Initialize the restart logic
8198 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308199
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008200 //Register the traffic monitor timer now
8201 if ( pHddCtx->cfg_ini->dynSplitscan)
8202 {
8203 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8204 VOS_TIMER_TYPE_SW,
8205 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8206 (void *)pHddCtx);
8207 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008208 goto success;
8209
8210err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008211#ifdef WLAN_KD_READY_NOTIFIER
8212 nl_srv_exit(pHddCtx->ptt_pid);
8213#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008214 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008215#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008216err_reg_netdev:
8217 unregister_netdevice_notifier(&hdd_netdev_notifier);
8218
8219err_free_power_on_lock:
8220 free_riva_power_on_lock("wlan");
8221
8222err_unregister_pmops:
8223 hddDevTmUnregisterNotifyCallback(pHddCtx);
8224 hddDeregisterPmOps(pHddCtx);
8225
Yue Ma0d4891e2013-08-06 17:01:45 -07008226 hdd_debugfs_exit(pHddCtx);
8227
Jeff Johnson295189b2012-06-20 16:38:30 -07008228#ifdef WLAN_BTAMP_FEATURE
8229err_bap_stop:
8230 WLANBAP_Stop(pVosContext);
8231#endif
8232
8233#ifdef WLAN_BTAMP_FEATURE
8234err_bap_close:
8235 WLANBAP_Close(pVosContext);
8236#endif
8237
Jeff Johnson295189b2012-06-20 16:38:30 -07008238err_close_adapter:
8239 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008240
8241#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308242 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008243#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008244
8245err_vosstop:
8246 vos_stop(pVosContext);
8247
Amar Singhala49cbc52013-10-08 18:37:44 -07008248err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008249 status = vos_sched_close( pVosContext );
8250 if (!VOS_IS_STATUS_SUCCESS(status)) {
8251 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8252 "%s: Failed to close VOSS Scheduler", __func__);
8253 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8254 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008255 vos_close(pVosContext );
8256
8257err_wiphy_unregister:
8258
8259#ifdef CONFIG_ENABLE_LINUX_REG
8260 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008261
Amar Singhal0a402232013-10-11 20:57:16 -07008262err_vos_nv_close:
8263
8264 vos_nv_close();
8265
Jeff Johnson295189b2012-06-20 16:38:30 -07008266err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008267#endif
8268
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008269 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008270
8271err_wdclose:
8272 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8273 vos_watchdog_close(pVosContext);
8274
Jeff Johnson295189b2012-06-20 16:38:30 -07008275err_config:
8276 kfree(pHddCtx->cfg_ini);
8277 pHddCtx->cfg_ini= NULL;
8278
8279err_free_hdd_context:
8280 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008281 wiphy_free(wiphy) ;
8282 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008283 VOS_BUG(1);
8284
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008285 if (hdd_is_ssr_required())
8286 {
8287 /* WDI timeout had happened during load, so SSR is needed here */
8288 subsystem_restart("wcnss");
8289 msleep(5000);
8290 }
8291 hdd_set_ssr_required (VOS_FALSE);
8292
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008293 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008294
8295success:
8296 EXIT();
8297 return 0;
8298}
8299
8300/**---------------------------------------------------------------------------
8301
Jeff Johnson32d95a32012-09-10 13:15:23 -07008302 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008303
Jeff Johnson32d95a32012-09-10 13:15:23 -07008304 This is the driver entry point - called in different timeline depending
8305 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008306
8307 \param - None
8308
8309 \return - 0 for success, non zero for failure
8310
8311 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008312static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008313{
8314 VOS_STATUS status;
8315 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008316 struct device *dev = NULL;
8317 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008318#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8319 int max_retries = 0;
8320#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008321
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308322#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8323 vos_wconn_trace_init();
8324#endif
8325
Jeff Johnson295189b2012-06-20 16:38:30 -07008326 ENTER();
8327
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008328#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008329 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008330#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008331
8332 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8333 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8334
8335 //Power Up Libra WLAN card first if not already powered up
8336 status = vos_chipPowerUp(NULL,NULL,NULL);
8337 if (!VOS_IS_STATUS_SUCCESS(status))
8338 {
8339 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8340 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308341#ifdef WLAN_OPEN_SOURCE
8342 wake_lock_destroy(&wlan_wake_lock);
8343#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008344 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008345 }
8346
Jeff Johnson295189b2012-06-20 16:38:30 -07008347#ifdef ANI_BUS_TYPE_PCI
8348
8349 dev = wcnss_wlan_get_device();
8350
8351#endif // ANI_BUS_TYPE_PCI
8352
8353#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008354
8355#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8356 /* wait until WCNSS driver downloads NV */
8357 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8358 msleep(1000);
8359 }
8360 if (max_retries >= 5) {
8361 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308362#ifdef WLAN_OPEN_SOURCE
8363 wake_lock_destroy(&wlan_wake_lock);
8364#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008365 return -ENODEV;
8366 }
8367#endif
8368
Jeff Johnson295189b2012-06-20 16:38:30 -07008369 dev = wcnss_wlan_get_device();
8370#endif // ANI_BUS_TYPE_PLATFORM
8371
8372
8373 do {
8374 if (NULL == dev) {
8375 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8376 ret_status = -1;
8377 break;
8378 }
8379
8380#ifdef MEMORY_DEBUG
8381 vos_mem_init();
8382#endif
8383
8384#ifdef TIMER_MANAGER
8385 vos_timer_manager_init();
8386#endif
8387
8388 /* Preopen VOSS so that it is ready to start at least SAL */
8389 status = vos_preOpen(&pVosContext);
8390
8391 if (!VOS_IS_STATUS_SUCCESS(status))
8392 {
8393 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8394 ret_status = -1;
8395 break;
8396 }
8397
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008398#ifndef MODULE
8399 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8400 */
8401 hdd_set_conparam((v_UINT_t)con_mode);
8402#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008403
8404 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008405 if (hdd_wlan_startup(dev))
8406 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008407 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008408 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008409 vos_preClose( &pVosContext );
8410 ret_status = -1;
8411 break;
8412 }
8413
8414 /* Cancel the vote for XO Core ON
8415 * This is done here for safety purposes in case we re-initialize without turning
8416 * it OFF in any error scenario.
8417 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008418 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008419 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008420 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008421 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8422 {
8423 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008424 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008425 }
8426 } while (0);
8427
8428 if (0 != ret_status)
8429 {
8430 //Assert Deep sleep signal now to put Libra HW in lowest power state
8431 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8432 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8433
8434 //Vote off any PMIC voltage supplies
8435 vos_chipPowerDown(NULL, NULL, NULL);
8436#ifdef TIMER_MANAGER
8437 vos_timer_exit();
8438#endif
8439#ifdef MEMORY_DEBUG
8440 vos_mem_exit();
8441#endif
8442
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008443#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008444 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008445#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008446 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8447 }
8448 else
8449 {
8450 //Send WLAN UP indication to Nlink Service
8451 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8452
8453 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008454 }
8455
8456 EXIT();
8457
8458 return ret_status;
8459}
8460
Jeff Johnson32d95a32012-09-10 13:15:23 -07008461/**---------------------------------------------------------------------------
8462
8463 \brief hdd_module_init() - Init Function
8464
8465 This is the driver entry point (invoked when module is loaded using insmod)
8466
8467 \param - None
8468
8469 \return - 0 for success, non zero for failure
8470
8471 --------------------------------------------------------------------------*/
8472#ifdef MODULE
8473static int __init hdd_module_init ( void)
8474{
8475 return hdd_driver_init();
8476}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008477#else /* #ifdef MODULE */
8478static int __init hdd_module_init ( void)
8479{
8480 /* Driver initialization is delayed to fwpath_changed_handler */
8481 return 0;
8482}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008483#endif /* #ifdef MODULE */
8484
Jeff Johnson295189b2012-06-20 16:38:30 -07008485
8486/**---------------------------------------------------------------------------
8487
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008488 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008489
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008490 This is the driver exit point (invoked when module is unloaded using rmmod
8491 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008492
8493 \param - None
8494
8495 \return - None
8496
8497 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008498static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008499{
8500 hdd_context_t *pHddCtx = NULL;
8501 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008502 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008503
8504 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8505
8506 //Get the global vos context
8507 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8508
8509 if(!pVosContext)
8510 {
8511 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8512 goto done;
8513 }
8514
8515 //Get the HDD context.
8516 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8517
8518 if(!pHddCtx)
8519 {
8520 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8521 }
8522 else
8523 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008524 while(isWDresetInProgress()) {
8525 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8526 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008527 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008528
8529 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8530 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8531 "%s:SSR never completed, fatal error", __func__);
8532 VOS_BUG(0);
8533 }
8534 }
8535
Jeff Johnson295189b2012-06-20 16:38:30 -07008536
8537 pHddCtx->isLoadUnloadInProgress = TRUE;
8538 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8539
8540 //Do all the cleanup before deregistering the driver
8541 hdd_wlan_exit(pHddCtx);
8542 }
8543
Jeff Johnson295189b2012-06-20 16:38:30 -07008544 vos_preClose( &pVosContext );
8545
8546#ifdef TIMER_MANAGER
8547 vos_timer_exit();
8548#endif
8549#ifdef MEMORY_DEBUG
8550 vos_mem_exit();
8551#endif
8552
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308553#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8554 vos_wconn_trace_exit();
8555#endif
8556
Jeff Johnson295189b2012-06-20 16:38:30 -07008557done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008558#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008559 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008560#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008561 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8562}
8563
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008564/**---------------------------------------------------------------------------
8565
8566 \brief hdd_module_exit() - Exit function
8567
8568 This is the driver exit point (invoked when module is unloaded using rmmod)
8569
8570 \param - None
8571
8572 \return - None
8573
8574 --------------------------------------------------------------------------*/
8575static void __exit hdd_module_exit(void)
8576{
8577 hdd_driver_exit();
8578}
8579
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008580#ifdef MODULE
8581static int fwpath_changed_handler(const char *kmessage,
8582 struct kernel_param *kp)
8583{
Jeff Johnson76052702013-04-16 13:55:05 -07008584 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008585}
8586
8587static int con_mode_handler(const char *kmessage,
8588 struct kernel_param *kp)
8589{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008590 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008591}
8592#else /* #ifdef MODULE */
8593/**---------------------------------------------------------------------------
8594
Jeff Johnson76052702013-04-16 13:55:05 -07008595 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008596
Jeff Johnson76052702013-04-16 13:55:05 -07008597 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008598 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008599 - invoked when module parameter fwpath is modified from userspace to signal
8600 initializing the WLAN driver or when con_mode is modified from userspace
8601 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008602
8603 \return - 0 for success, non zero for failure
8604
8605 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008606static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008607{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008608 int ret_status;
8609
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008610 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008611 ret_status = hdd_driver_init();
8612 wlan_hdd_inited = ret_status ? 0 : 1;
8613 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008614 }
8615
8616 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008617
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008618 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008619
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008620 ret_status = hdd_driver_init();
8621 wlan_hdd_inited = ret_status ? 0 : 1;
8622 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008623}
8624
Jeff Johnson295189b2012-06-20 16:38:30 -07008625/**---------------------------------------------------------------------------
8626
Jeff Johnson76052702013-04-16 13:55:05 -07008627 \brief fwpath_changed_handler() - Handler Function
8628
8629 Handle changes to the fwpath parameter
8630
8631 \return - 0 for success, non zero for failure
8632
8633 --------------------------------------------------------------------------*/
8634static int fwpath_changed_handler(const char *kmessage,
8635 struct kernel_param *kp)
8636{
8637 int ret;
8638
8639 ret = param_set_copystring(kmessage, kp);
8640 if (0 == ret)
8641 ret = kickstart_driver();
8642 return ret;
8643}
8644
8645/**---------------------------------------------------------------------------
8646
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008647 \brief con_mode_handler() -
8648
8649 Handler function for module param con_mode when it is changed by userspace
8650 Dynamically linked - do nothing
8651 Statically linked - exit and init driver, as in rmmod and insmod
8652
Jeff Johnson76052702013-04-16 13:55:05 -07008653 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008654
Jeff Johnson76052702013-04-16 13:55:05 -07008655 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008656
8657 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008658static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008659{
Jeff Johnson76052702013-04-16 13:55:05 -07008660 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008661
Jeff Johnson76052702013-04-16 13:55:05 -07008662 ret = param_set_int(kmessage, kp);
8663 if (0 == ret)
8664 ret = kickstart_driver();
8665 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008666}
8667#endif /* #ifdef MODULE */
8668
8669/**---------------------------------------------------------------------------
8670
Jeff Johnson295189b2012-06-20 16:38:30 -07008671 \brief hdd_get_conparam() -
8672
8673 This is the driver exit point (invoked when module is unloaded using rmmod)
8674
8675 \param - None
8676
8677 \return - tVOS_CON_MODE
8678
8679 --------------------------------------------------------------------------*/
8680tVOS_CON_MODE hdd_get_conparam ( void )
8681{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008682#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008683 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008684#else
8685 return (tVOS_CON_MODE)curr_con_mode;
8686#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008687}
8688void hdd_set_conparam ( v_UINT_t newParam )
8689{
8690 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008691#ifndef MODULE
8692 curr_con_mode = con_mode;
8693#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008694}
8695/**---------------------------------------------------------------------------
8696
8697 \brief hdd_softap_sta_deauth() - function
8698
8699 This to take counter measure to handle deauth req from HDD
8700
8701 \param - pAdapter - Pointer to the HDD
8702
8703 \param - enable - boolean value
8704
8705 \return - None
8706
8707 --------------------------------------------------------------------------*/
8708
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008709VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008710{
Jeff Johnson295189b2012-06-20 16:38:30 -07008711 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008712 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008713
8714 ENTER();
8715
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008716 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8717 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008718
8719 //Ignore request to deauth bcmc station
8720 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008721 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008722
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008723 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008724
8725 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008726 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008727}
8728
8729/**---------------------------------------------------------------------------
8730
8731 \brief hdd_softap_sta_disassoc() - function
8732
8733 This to take counter measure to handle deauth req from HDD
8734
8735 \param - pAdapter - Pointer to the HDD
8736
8737 \param - enable - boolean value
8738
8739 \return - None
8740
8741 --------------------------------------------------------------------------*/
8742
8743void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8744{
8745 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8746
8747 ENTER();
8748
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308749 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008750
8751 //Ignore request to disassoc bcmc station
8752 if( pDestMacAddress[0] & 0x1 )
8753 return;
8754
8755 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8756}
8757
8758void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8759{
8760 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8761
8762 ENTER();
8763
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308764 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008765
8766 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8767}
8768
Jeff Johnson295189b2012-06-20 16:38:30 -07008769/**---------------------------------------------------------------------------
8770 *
8771 * \brief hdd_get__concurrency_mode() -
8772 *
8773 *
8774 * \param - None
8775 *
8776 * \return - CONCURRENCY MODE
8777 *
8778 * --------------------------------------------------------------------------*/
8779tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8780{
8781 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8782 hdd_context_t *pHddCtx;
8783
8784 if (NULL != pVosContext)
8785 {
8786 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8787 if (NULL != pHddCtx)
8788 {
8789 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8790 }
8791 }
8792
8793 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008794 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008795 return VOS_STA;
8796}
8797
8798/* Decide whether to allow/not the apps power collapse.
8799 * Allow apps power collapse if we are in connected state.
8800 * if not, allow only if we are in IMPS */
8801v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8802{
8803 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008804 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008805 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008806 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8807 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8808 hdd_adapter_t *pAdapter = NULL;
8809 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008810 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008811
Jeff Johnson295189b2012-06-20 16:38:30 -07008812 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8813 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008814
Yathish9f22e662012-12-10 14:21:35 -08008815 concurrent_state = hdd_get_concurrency_mode();
8816
8817#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8818 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8819 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8820 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8821 return TRUE;
8822#endif
8823
Jeff Johnson295189b2012-06-20 16:38:30 -07008824 /*loop through all adapters. TBD fix for Concurrency */
8825 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8826 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8827 {
8828 pAdapter = pAdapterNode->pAdapter;
8829 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8830 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8831 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008832 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008833 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008834 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008835 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8836 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008837 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008838 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008839 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8840 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008841 return FALSE;
8842 }
8843 }
8844 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8845 pAdapterNode = pNext;
8846 }
8847 return TRUE;
8848}
8849
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008850/* Decides whether to send suspend notification to Riva
8851 * if any adapter is in BMPS; then it is required */
8852v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8853{
8854 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8855 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8856
8857 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8858 {
8859 return TRUE;
8860 }
8861 return FALSE;
8862}
8863
Jeff Johnson295189b2012-06-20 16:38:30 -07008864void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8865{
8866 switch(mode)
8867 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008868 case VOS_STA_MODE:
8869 case VOS_P2P_CLIENT_MODE:
8870 case VOS_P2P_GO_MODE:
8871 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008872 pHddCtx->concurrency_mode |= (1 << mode);
8873 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008874 break;
8875 default:
8876 break;
8877
8878 }
8879 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8880 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8881}
8882
8883
8884void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8885{
8886 switch(mode)
8887 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008888 case VOS_STA_MODE:
8889 case VOS_P2P_CLIENT_MODE:
8890 case VOS_P2P_GO_MODE:
8891 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008892 pHddCtx->no_of_sessions[mode]--;
8893 if (!(pHddCtx->no_of_sessions[mode]))
8894 pHddCtx->concurrency_mode &= (~(1 << mode));
8895 break;
8896 default:
8897 break;
8898 }
8899 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8900 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8901}
8902
Jeff Johnsone7245742012-09-05 17:12:55 -07008903/**---------------------------------------------------------------------------
8904 *
8905 * \brief wlan_hdd_restart_init
8906 *
8907 * This function initalizes restart timer/flag. An internal function.
8908 *
8909 * \param - pHddCtx
8910 *
8911 * \return - None
8912 *
8913 * --------------------------------------------------------------------------*/
8914
8915static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8916{
8917 /* Initialize */
8918 pHddCtx->hdd_restart_retries = 0;
8919 atomic_set(&pHddCtx->isRestartInProgress, 0);
8920 vos_timer_init(&pHddCtx->hdd_restart_timer,
8921 VOS_TIMER_TYPE_SW,
8922 wlan_hdd_restart_timer_cb,
8923 pHddCtx);
8924}
8925/**---------------------------------------------------------------------------
8926 *
8927 * \brief wlan_hdd_restart_deinit
8928 *
8929 * This function cleans up the resources used. An internal function.
8930 *
8931 * \param - pHddCtx
8932 *
8933 * \return - None
8934 *
8935 * --------------------------------------------------------------------------*/
8936
8937static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8938{
8939
8940 VOS_STATUS vos_status;
8941 /* Block any further calls */
8942 atomic_set(&pHddCtx->isRestartInProgress, 1);
8943 /* Cleanup */
8944 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8945 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008946 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008947 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8948 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008949 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008950
8951}
8952
8953/**---------------------------------------------------------------------------
8954 *
8955 * \brief wlan_hdd_framework_restart
8956 *
8957 * This function uses a cfg80211 API to start a framework initiated WLAN
8958 * driver module unload/load.
8959 *
8960 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8961 *
8962 *
8963 * \param - pHddCtx
8964 *
8965 * \return - VOS_STATUS_SUCCESS: Success
8966 * VOS_STATUS_E_EMPTY: Adapter is Empty
8967 * VOS_STATUS_E_NOMEM: No memory
8968
8969 * --------------------------------------------------------------------------*/
8970
8971static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8972{
8973 VOS_STATUS status = VOS_STATUS_SUCCESS;
8974 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008975 int len = (sizeof (struct ieee80211_mgmt));
8976 struct ieee80211_mgmt *mgmt = NULL;
8977
8978 /* Prepare the DEAUTH managment frame with reason code */
8979 mgmt = kzalloc(len, GFP_KERNEL);
8980 if(mgmt == NULL)
8981 {
8982 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8983 "%s: memory allocation failed (%d bytes)", __func__, len);
8984 return VOS_STATUS_E_NOMEM;
8985 }
8986 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008987
8988 /* Iterate over all adapters/devices */
8989 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8990 do
8991 {
8992 if( (status == VOS_STATUS_SUCCESS) &&
8993 pAdapterNode &&
8994 pAdapterNode->pAdapter)
8995 {
8996 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8997 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8998 pAdapterNode->pAdapter->dev->name,
8999 pAdapterNode->pAdapter->device_mode,
9000 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009001 /*
9002 * CFG80211 event to restart the driver
9003 *
9004 * 'cfg80211_send_unprot_deauth' sends a
9005 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9006 * of SME(Linux Kernel) state machine.
9007 *
9008 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9009 * the driver.
9010 *
9011 */
9012
9013 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009014 }
9015 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9016 pAdapterNode = pNext;
9017 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9018
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009019
9020 /* Free the allocated management frame */
9021 kfree(mgmt);
9022
Jeff Johnsone7245742012-09-05 17:12:55 -07009023 /* Retry until we unload or reach max count */
9024 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9025 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9026
9027 return status;
9028
9029}
9030/**---------------------------------------------------------------------------
9031 *
9032 * \brief wlan_hdd_restart_timer_cb
9033 *
9034 * Restart timer callback. An internal function.
9035 *
9036 * \param - User data:
9037 *
9038 * \return - None
9039 *
9040 * --------------------------------------------------------------------------*/
9041
9042void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9043{
9044 hdd_context_t *pHddCtx = usrDataForCallback;
9045 wlan_hdd_framework_restart(pHddCtx);
9046 return;
9047
9048}
9049
9050
9051/**---------------------------------------------------------------------------
9052 *
9053 * \brief wlan_hdd_restart_driver
9054 *
9055 * This function sends an event to supplicant to restart the WLAN driver.
9056 *
9057 * This function is called from vos_wlanRestart.
9058 *
9059 * \param - pHddCtx
9060 *
9061 * \return - VOS_STATUS_SUCCESS: Success
9062 * VOS_STATUS_E_EMPTY: Adapter is Empty
9063 * VOS_STATUS_E_ALREADY: Request already in progress
9064
9065 * --------------------------------------------------------------------------*/
9066VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9067{
9068 VOS_STATUS status = VOS_STATUS_SUCCESS;
9069
9070 /* A tight check to make sure reentrancy */
9071 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9072 {
9073 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9074 "%s: WLAN restart is already in progress", __func__);
9075
9076 return VOS_STATUS_E_ALREADY;
9077 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009078 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009079#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009080 wcnss_reset_intr();
9081#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009082
Jeff Johnsone7245742012-09-05 17:12:55 -07009083 return status;
9084}
9085
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009086/*
9087 * API to find if there is any STA or P2P-Client is connected
9088 */
9089VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9090{
9091 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9092}
Jeff Johnsone7245742012-09-05 17:12:55 -07009093
Jeff Johnson295189b2012-06-20 16:38:30 -07009094//Register the module init/exit functions
9095module_init(hdd_module_init);
9096module_exit(hdd_module_exit);
9097
9098MODULE_LICENSE("Dual BSD/GPL");
9099MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9100MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9101
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009102module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9103 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009104
Jeff Johnson76052702013-04-16 13:55:05 -07009105module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009106 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009107
9108module_param(enable_dfs_chan_scan, int,
9109 S_IRUSR | S_IRGRP | S_IROTH);
9110
9111module_param(enable_11d, int,
9112 S_IRUSR | S_IRGRP | S_IROTH);
9113
9114module_param(country_code, charp,
9115 S_IRUSR | S_IRGRP | S_IROTH);