blob: d7d663009e48b2251bc871d224c64014d95b3900 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Gopichand Nakkala92f07d82013-01-08 21:16:34 -08002 * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21/*
Jeff Johnson32d95a32012-09-10 13:15:23 -070022 * Copyright (c) 2012, The Linux Foundation. All rights reserved.
Jeff Johnson295189b2012-06-20 16:38:30 -070023 *
24 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
25 *
26 *
27 * Permission to use, copy, modify, and/or distribute this software for
28 * any purpose with or without fee is hereby granted, provided that the
29 * above copyright notice and this permission notice appear in all
30 * copies.
31 *
32 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
33 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
35 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
36 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
37 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
38 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
39 * PERFORMANCE OF THIS SOFTWARE.
40 */
41
42/*========================================================================
43
44 \file wlan_hdd_main.c
45
46 \brief WLAN Host Device Driver implementation
47
48 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
49
50 Qualcomm Confidential and Proprietary.
51
52 ========================================================================*/
53
54/**=========================================================================
55
56 EDIT HISTORY FOR FILE
57
58
59 This section contains comments describing changes made to the module.
60 Notice that changes are listed in reverse chronological order.
61
62
63 $Header:$ $DateTime: $ $Author: $
64
65
66 when who what, where, why
67 -------- --- --------------------------------------------------------
68 04/5/09 Shailender Created module.
69 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
70 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
71 ==========================================================================*/
72
73/*--------------------------------------------------------------------------
74 Include Files
75 ------------------------------------------------------------------------*/
76//#include <wlan_qct_driver.h>
77#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070078#include <vos_api.h>
79#include <vos_sched.h>
80#include <vos_power.h>
81#include <linux/etherdevice.h>
82#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070083#ifdef ANI_BUS_TYPE_PLATFORM
84#include <linux/wcnss_wlan.h>
85#endif //ANI_BUS_TYPE_PLATFORM
86#ifdef ANI_BUS_TYPE_PCI
87#include "wcnss_wlan.h"
88#endif /* ANI_BUS_TYPE_PCI */
89#include <wlan_hdd_tx_rx.h>
90#include <palTimer.h>
91#include <wniApi.h>
92#include <wlan_nlink_srv.h>
93#include <wlan_btc_svc.h>
94#include <wlan_hdd_cfg.h>
95#include <wlan_ptt_sock_svc.h>
96#include <wlan_hdd_wowl.h>
97#include <wlan_hdd_misc.h>
98#include <wlan_hdd_wext.h>
99#ifdef WLAN_BTAMP_FEATURE
100#include <bap_hdd_main.h>
101#include <bapInternal.h>
102#endif // WLAN_BTAMP_FEATURE
103
Jeff Johnson295189b2012-06-20 16:38:30 -0700104#include <linux/wireless.h>
105#include <net/cfg80211.h>
106#include "wlan_hdd_cfg80211.h"
107#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700108#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700109int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700110#include "sapApi.h"
111#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700112#include <linux/ctype.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700113#include <mach/subsystem_restart.h>
114#include <wlan_hdd_hostapd.h>
115#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700116#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700117#include "wlan_hdd_dev_pwr.h"
118#ifdef WLAN_BTAMP_FEATURE
119#include "bap_hdd_misc.h"
120#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700121#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700122#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800123#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530124#ifdef FEATURE_WLAN_TDLS
125#include "wlan_hdd_tdls.h"
126#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700127#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700128
129#ifdef MODULE
130#define WLAN_MODULE_NAME module_name(THIS_MODULE)
131#else
132#define WLAN_MODULE_NAME "wlan"
133#endif
134
135#ifdef TIMER_MANAGER
136#define TIMER_MANAGER_STR " +TIMER_MANAGER"
137#else
138#define TIMER_MANAGER_STR ""
139#endif
140
141#ifdef MEMORY_DEBUG
142#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
143#else
144#define MEMORY_DEBUG_STR ""
145#endif
146
147/* the Android framework expects this param even though we don't use it */
148#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700149static char fwpath_buffer[BUF_LEN];
150static struct kparam_string fwpath = {
151 .string = fwpath_buffer,
152 .maxlen = BUF_LEN,
153};
Arif Hussain66559122013-11-21 10:11:40 -0800154
155static char *country_code;
156static int enable_11d = -1;
157static int enable_dfs_chan_scan = -1;
158
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700159#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700160static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700161#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700162
Jeff Johnsone7245742012-09-05 17:12:55 -0700163/*
164 * The rate at which the driver sends RESTART event to supplicant
165 * once the function 'vos_wlanRestart()' is called
166 *
167 */
168#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
169#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700170
171/*
172 * Size of Driver command strings from upper layer
173 */
174#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
175#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
176
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700177#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
178#define TID_MIN_VALUE 0
179#define TID_MAX_VALUE 15
180static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
181 tAniTrafStrmMetrics* pTsmMetrics);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -0800182static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
183 tCsrCcxBeaconReq *pCcxBcnReq);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700184#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
185
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700186/*
187 * Driver miracast parameters 0-Disabled
188 * 1-Source, 2-Sink
189 */
190#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
191#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
192
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800193#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700194static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700195#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700196/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700197static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700198
199//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700200static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
201static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
202static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
203void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800204void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700205
Jeff Johnson295189b2012-06-20 16:38:30 -0700206v_U16_t hdd_select_queue(struct net_device *dev,
207 struct sk_buff *skb);
208
209#ifdef WLAN_FEATURE_PACKET_FILTERING
210static void hdd_set_multicast_list(struct net_device *dev);
211#endif
212
213void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
Amar Singhal4c723bd2013-03-25 18:14:15 -0700214int isWDresetInProgress(void);
Jeff Johnson295189b2012-06-20 16:38:30 -0700215
216extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Amar Singhal0a402232013-10-11 20:57:16 -0700217
Srinivas Girigowdade697412013-02-14 16:31:48 -0800218#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
219void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
220static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700221static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
222 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
223 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700224static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
225 tANI_U8 *pTargetApBssid,
226 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800227#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700228#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
229VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
230#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
231
Jeff Johnson295189b2012-06-20 16:38:30 -0700232static int hdd_netdev_notifier_call(struct notifier_block * nb,
233 unsigned long state,
234 void *ndev)
235{
236 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700237 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700238 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700239#ifdef WLAN_BTAMP_FEATURE
240 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700241#endif
242
243 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700244 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700245 (strncmp(dev->name, "p2p", 3)))
246 return NOTIFY_DONE;
247
248 if (isWDresetInProgress())
Jeff Johnson295189b2012-06-20 16:38:30 -0700249 return NOTIFY_DONE;
250
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700252 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700253
Jeff Johnson27cee452013-03-27 11:10:24 -0700254 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700255 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800256 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700257 VOS_ASSERT(0);
258 return NOTIFY_DONE;
259 }
260
Jeff Johnson27cee452013-03-27 11:10:24 -0700261 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
262 if (NULL == pHddCtx)
263 {
264 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
265 VOS_ASSERT(0);
266 return NOTIFY_DONE;
267 }
268
269 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
270 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700271
272 switch (state) {
273 case NETDEV_REGISTER:
274 break;
275
276 case NETDEV_UNREGISTER:
277 break;
278
279 case NETDEV_UP:
280 break;
281
282 case NETDEV_DOWN:
283 break;
284
285 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700286 if(TRUE == pAdapter->isLinkUpSvcNeeded)
287 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700288 break;
289
290 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700291 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700292 {
293 int result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800294 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +0530295 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -0700296 result = wait_for_completion_interruptible_timeout(
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800297 &pHddCtx->scan_info.abortscan_event_var,
Jeff Johnson295189b2012-06-20 16:38:30 -0700298 msecs_to_jiffies(WLAN_WAIT_TIME_ABORTSCAN));
299 if(!result)
300 {
301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Jeff Johnson902c9832012-12-10 14:28:09 -0800302 "%s: Timeout occurred while waiting for abortscan" ,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700303 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700304 }
305 }
306 else
307 {
308 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700309 "%s: Scan is not Pending from user" , __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700310 }
311#ifdef WLAN_BTAMP_FEATURE
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -0700312 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"%s: disabling AMP", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700313 status = WLANBAP_StopAmp();
314 if(VOS_STATUS_SUCCESS != status )
315 {
316 pHddCtx->isAmpAllowed = VOS_TRUE;
317 hddLog(VOS_TRACE_LEVEL_FATAL,
318 "%s: Failed to stop AMP", __func__);
319 }
320 else
321 {
322 //a state m/c implementation in PAL is TBD to avoid this delay
323 msleep(500);
Jeff Johnson04dd8a82012-06-29 20:41:40 -0700324 if ( pHddCtx->isAmpAllowed )
325 {
326 WLANBAP_DeregisterFromHCI();
327 pHddCtx->isAmpAllowed = VOS_FALSE;
328 }
Jeff Johnson295189b2012-06-20 16:38:30 -0700329 }
330#endif //WLAN_BTAMP_FEATURE
331 break;
332
333 default:
334 break;
335 }
336
337 return NOTIFY_DONE;
338}
339
340struct notifier_block hdd_netdev_notifier = {
341 .notifier_call = hdd_netdev_notifier_call,
342};
343
344/*---------------------------------------------------------------------------
345 * Function definitions
346 *-------------------------------------------------------------------------*/
Jeff Johnson295189b2012-06-20 16:38:30 -0700347void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx);
348void hdd_register_mcast_bcast_filter(hdd_context_t *pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -0700349//variable to hold the insmod parameters
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700350static int con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -0700351#ifndef MODULE
352/* current con_mode - used only for statically linked driver
353 * con_mode is changed by userspace to indicate a mode change which will
354 * result in calling the module exit and init functions. The module
355 * exit function will clean up based on the value of con_mode prior to it
356 * being changed by userspace. So curr_con_mode records the current con_mode
357 * for exit when con_mode becomes the next mode for init
358 */
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700359static int curr_con_mode;
Jeff Johnson295189b2012-06-20 16:38:30 -0700360#endif
361
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -0800362/**---------------------------------------------------------------------------
363
364 \brief hdd_vos_trace_enable() - Configure initial VOS Trace enable
365
366 Called immediately after the cfg.ini is read in order to configure
367 the desired trace levels.
368
369 \param - moduleId - module whose trace level is being configured
370 \param - bitmask - bitmask of log levels to be enabled
371
372 \return - void
373
374 --------------------------------------------------------------------------*/
375static void hdd_vos_trace_enable(VOS_MODULE_ID moduleId, v_U32_t bitmask)
376{
377 wpt_tracelevel level;
378
379 /* if the bitmask is the default value, then a bitmask was not
380 specified in cfg.ini, so leave the logging level alone (it
381 will remain at the "compiled in" default value) */
382 if (CFG_VOS_TRACE_ENABLE_DEFAULT == bitmask)
383 {
384 return;
385 }
386
387 /* a mask was specified. start by disabling all logging */
388 vos_trace_setValue(moduleId, VOS_TRACE_LEVEL_NONE, 0);
389
390 /* now cycle through the bitmask until all "set" bits are serviced */
391 level = VOS_TRACE_LEVEL_FATAL;
392 while (0 != bitmask)
393 {
394 if (bitmask & 1)
395 {
396 vos_trace_setValue(moduleId, level, 1);
397 }
398 level++;
399 bitmask >>= 1;
400 }
401}
402
403
Jeff Johnson295189b2012-06-20 16:38:30 -0700404/**---------------------------------------------------------------------------
405
406 \brief hdd_wdi_trace_enable() - Configure initial WDI Trace enable
407
408 Called immediately after the cfg.ini is read in order to configure
409 the desired trace levels in the WDI.
410
411 \param - moduleId - module whose trace level is being configured
412 \param - bitmask - bitmask of log levels to be enabled
413
414 \return - void
415
416 --------------------------------------------------------------------------*/
417static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask)
418{
419 wpt_tracelevel level;
420
421 /* if the bitmask is the default value, then a bitmask was not
422 specified in cfg.ini, so leave the logging level alone (it
423 will remain at the "compiled in" default value) */
424 if (CFG_WDI_TRACE_ENABLE_DEFAULT == bitmask)
425 {
426 return;
427 }
428
429 /* a mask was specified. start by disabling all logging */
430 wpalTraceSetLevel(moduleId, eWLAN_PAL_TRACE_LEVEL_NONE, 0);
431
432 /* now cycle through the bitmask until all "set" bits are serviced */
433 level = eWLAN_PAL_TRACE_LEVEL_FATAL;
434 while (0 != bitmask)
435 {
436 if (bitmask & 1)
437 {
438 wpalTraceSetLevel(moduleId, level, 1);
439 }
440 level++;
441 bitmask >>= 1;
442 }
443}
Jeff Johnson295189b2012-06-20 16:38:30 -0700444
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530445/*
446 * FUNCTION: wlan_hdd_validate_context
447 * This function is used to check the HDD context
448 */
449int wlan_hdd_validate_context(hdd_context_t *pHddCtx)
450{
451 ENTER();
452
453 if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini)
454 {
455 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
456 "%s: HDD context is Null", __func__);
457 return -ENODEV;
458 }
459
460 if (pHddCtx->isLogpInProgress)
461 {
462 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
463 "%s: LOGP in Progress. Ignore!!!", __func__);
464 return -EAGAIN;
465 }
466
467 if (pHddCtx->isLoadUnloadInProgress)
468 {
469 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
470 "%s: Unloading/Loading in Progress. Ignore!!!", __func__);
471 return -EAGAIN;
472 }
473 return 0;
474}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700475#ifdef CONFIG_ENABLE_LINUX_REG
476void hdd_checkandupdate_phymode( hdd_context_t *pHddCtx)
477{
478 hdd_adapter_t *pAdapter = NULL;
479 hdd_station_ctx_t *pHddStaCtx = NULL;
480 eCsrPhyMode phyMode;
481 hdd_config_t *cfg_param = NULL;
Gopichand Nakkalaf502e2b2013-05-24 18:34:25 +0530482
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700483 if (NULL == pHddCtx)
484 {
485 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
486 "HDD Context is null !!");
487 return ;
488 }
489
490 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
491 if (NULL == pAdapter)
492 {
493 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
494 "pAdapter is null !!");
495 return ;
496 }
497
498 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
499 if (NULL == pHddStaCtx)
500 {
501 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
502 "pHddStaCtx is null !!");
503 return ;
504 }
505
506 cfg_param = pHddCtx->cfg_ini;
507 if (NULL == cfg_param)
508 {
509 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
510 "cfg_params not available !!");
511 return ;
512 }
513
514 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
515
516 if (!pHddCtx->isVHT80Allowed)
517 {
518 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
519 (eCSR_DOT11_MODE_11ac == phyMode) ||
520 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
521 {
522 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
523 "Setting phymode to 11n!!");
524 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
525 }
526 }
527 else
528 {
529 /*New country Supports 11ac as well resetting value back from .ini*/
530 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
531 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
532 return ;
533 }
534
535 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
536 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
537 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
538 {
539 VOS_STATUS vosStatus;
540
541 // need to issue a disconnect to CSR.
542 INIT_COMPLETION(pAdapter->disconnect_comp_var);
543 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
544 pAdapter->sessionId,
545 eCSR_DISCONNECT_REASON_UNSPECIFIED );
546
547 if (VOS_STATUS_SUCCESS == vosStatus)
548 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
549 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
550
551 }
552}
553#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530554void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
555{
556 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
557 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
558 hdd_config_t *cfg_param;
559 eCsrPhyMode phyMode;
560
561 if (NULL == pHddCtx)
562 {
563 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
564 "HDD Context is null !!");
565 return ;
566 }
567
568 cfg_param = pHddCtx->cfg_ini;
569
570 if (NULL == cfg_param)
571 {
572 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
573 "cfg_params not available !!");
574 return ;
575 }
576
577 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
578
579 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
580 {
581 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
582 (eCSR_DOT11_MODE_11ac == phyMode) ||
583 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
584 {
585 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
586 "Setting phymode to 11n!!");
587 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
588 }
589 }
590 else
591 {
592 /*New country Supports 11ac as well resetting value back from .ini*/
593 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
594 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
595 return ;
596 }
597
598 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
599 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
600 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
601 {
602 VOS_STATUS vosStatus;
603
604 // need to issue a disconnect to CSR.
605 INIT_COMPLETION(pAdapter->disconnect_comp_var);
606 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
607 pAdapter->sessionId,
608 eCSR_DISCONNECT_REASON_UNSPECIFIED );
609
610 if (VOS_STATUS_SUCCESS == vosStatus)
611 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
612 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
613
614 }
615}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700616#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530617
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700618void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
619{
620 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
621 hdd_config_t *cfg_param;
622
623 if (NULL == pHddCtx)
624 {
625 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
626 "HDD Context is null !!");
627 return ;
628 }
629
630 cfg_param = pHddCtx->cfg_ini;
631
632 if (NULL == cfg_param)
633 {
634 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
635 "cfg_params not available !!");
636 return ;
637 }
638
639 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
640 {
641 /*New country doesn't support DFS */
642 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
643 }
644 else
645 {
646 /*New country Supports DFS as well resetting value back from .ini*/
647 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
648 }
649
650}
651
Rajeev79dbe4c2013-10-05 11:03:42 +0530652#ifdef FEATURE_WLAN_BATCH_SCAN
653
654/**---------------------------------------------------------------------------
655
656 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
657 input string
658
659 This function extracts assigned integer from string in below format:
660 "STRING=10" : extracts integer 10 from this string
661
662 \param - pInPtr Pointer to input string
663 \param - base Base for string to int conversion(10 for decimal 16 for hex)
664 \param - pOutPtr Pointer to variable in which extracted integer needs to be
665 assigned
666 \param - pLastArg to tell whether it is last arguement in input string or
667 not
668
669 \return - NULL for failure cases
670 pointer to next arguement in input string for success cases
671 --------------------------------------------------------------------------*/
672static tANI_U8 *
673hdd_extract_assigned_int_from_str
674(
675 tANI_U8 *pInPtr,
676 tANI_U8 base,
677 tANI_U32 *pOutPtr,
678 tANI_U8 *pLastArg
679)
680{
681 int tempInt;
682 int v = 0;
683 char buf[32];
684 int val = 0;
685 *pLastArg = FALSE;
686
687 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
688 if (NULL == pInPtr)
689 {
690 return NULL;
691 }
692
693 pInPtr++;
694
695 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
696
697 val = sscanf(pInPtr, "%32s ", buf);
698 if (val < 0 && val > strlen(pInPtr))
699 {
700 return NULL;
701 }
702 pInPtr += val;
703 v = kstrtos32(buf, base, &tempInt);
704 if (v < 0)
705 {
706 return NULL;
707 }
708 *pOutPtr = tempInt;
709
710 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
711 if (NULL == pInPtr)
712 {
713 *pLastArg = TRUE;
714 return NULL;
715 }
716 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
717
718 return pInPtr;
719}
720
721/**---------------------------------------------------------------------------
722
723 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
724 input string
725
726 This function extracts assigned character from string in below format:
727 "STRING=A" : extracts char 'A' from this string
728
729 \param - pInPtr Pointer to input string
730 \param - pOutPtr Pointer to variable in which extracted char needs to be
731 assigned
732 \param - pLastArg to tell whether it is last arguement in input string or
733 not
734
735 \return - NULL for failure cases
736 pointer to next arguement in input string for success cases
737 --------------------------------------------------------------------------*/
738static tANI_U8 *
739hdd_extract_assigned_char_from_str
740(
741 tANI_U8 *pInPtr,
742 tANI_U8 *pOutPtr,
743 tANI_U8 *pLastArg
744)
745{
746 *pLastArg = FALSE;
747
748 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
749 if (NULL == pInPtr)
750 {
751 return NULL;
752 }
753
754 pInPtr++;
755
756 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
757
758 *pOutPtr = *pInPtr;
759
760 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
761 if (NULL == pInPtr)
762 {
763 *pLastArg = TRUE;
764 return NULL;
765 }
766 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
767
768 return pInPtr;
769}
770
771
772/**---------------------------------------------------------------------------
773
774 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
775
776 This function parses set batch scan command in below format:
777 WLS_BATCHING_SET <space> followed by below arguements
778 "SCANFREQ=XX" : Optional defaults to 30 sec
779 "MSCAN=XX" : Required number of scans to attempt to batch
780 "BESTN=XX" : Best Network (RSSI) defaults to 16
781 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
782 A. implies only 5 GHz , B. implies only 2.4GHz
783 "RTT=X" : optional defaults to 0
784 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
785 error
786
787 For example input commands:
788 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
789 translated into set batch scan with following parameters:
790 a) Frequence 60 seconds
791 b) Batch 10 scans together
792 c) Best RSSI to be 20
793 d) 5GHz band only
794 e) RTT is equal to 0
795
796 \param - pValue Pointer to input channel list
797 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
798
799 \return - 0 for success non-zero for failure
800
801 --------------------------------------------------------------------------*/
802static int
803hdd_parse_set_batchscan_command
804(
805 tANI_U8 *pValue,
806 tSirSetBatchScanReq *pHddSetBatchScanReq
807)
808{
809 tANI_U8 *inPtr = pValue;
810 tANI_U8 val = 0;
811 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800812 tANI_U32 nScanFreq;
813 tANI_U32 nMscan;
814 tANI_U32 nBestN;
815 tANI_U8 ucRfBand;
816 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800817 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530818
819 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800820 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
821 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
822 nRtt = 0;
823 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530824
825 /*go to space after WLS_BATCHING_SET command*/
826 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
827 /*no argument after the command*/
828 if (NULL == inPtr)
829 {
830 return -EINVAL;
831 }
832
833 /*no space after the command*/
834 else if (SPACE_ASCII_VALUE != *inPtr)
835 {
836 return -EINVAL;
837 }
838
839 /*removing empty spaces*/
840 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
841
842 /*no argument followed by spaces*/
843 if ('\0' == *inPtr)
844 {
845 return -EINVAL;
846 }
847
848 /*check and parse SCANFREQ*/
849 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
850 {
851 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800852 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800853
Rajeev Kumarc933d982013-11-18 20:04:20 -0800854 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800855 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800856 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800857 }
858
Rajeev79dbe4c2013-10-05 11:03:42 +0530859 if ( (NULL == inPtr) || (TRUE == lastArg))
860 {
861 return -EINVAL;
862 }
863 }
864
865 /*check and parse MSCAN*/
866 if ((strncmp(inPtr, "MSCAN", 5) == 0))
867 {
868 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800869 &nMscan, &lastArg);
870
871 if (0 == nMscan)
872 {
873 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
874 "invalid MSCAN=%d", nMscan);
875 return -EINVAL;
876 }
877
Rajeev79dbe4c2013-10-05 11:03:42 +0530878 if (TRUE == lastArg)
879 {
880 goto done;
881 }
882 else if (NULL == inPtr)
883 {
884 return -EINVAL;
885 }
886 }
887 else
888 {
889 return -EINVAL;
890 }
891
892 /*check and parse BESTN*/
893 if ((strncmp(inPtr, "BESTN", 5) == 0))
894 {
895 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800896 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800897
Rajeev Kumarc933d982013-11-18 20:04:20 -0800898 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800899 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800900 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800901 }
902
Rajeev79dbe4c2013-10-05 11:03:42 +0530903 if (TRUE == lastArg)
904 {
905 goto done;
906 }
907 else if (NULL == inPtr)
908 {
909 return -EINVAL;
910 }
911 }
912
913 /*check and parse CHANNEL*/
914 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
915 {
916 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800917
Rajeev79dbe4c2013-10-05 11:03:42 +0530918 if (('A' == val) || ('a' == val))
919 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800920 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530921 }
922 else if (('B' == val) || ('b' == val))
923 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800924 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530925 }
926 else
927 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800928 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
929 }
930
931 if (TRUE == lastArg)
932 {
933 goto done;
934 }
935 else if (NULL == inPtr)
936 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530937 return -EINVAL;
938 }
939 }
940
941 /*check and parse RTT*/
942 if ((strncmp(inPtr, "RTT", 3) == 0))
943 {
944 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800945 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530946 if (TRUE == lastArg)
947 {
948 goto done;
949 }
950 if (NULL == inPtr)
951 {
952 return -EINVAL;
953 }
954 }
955
956
957done:
958
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800959 pHddSetBatchScanReq->scanFrequency = nScanFreq;
960 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
961 pHddSetBatchScanReq->bestNetwork = nBestN;
962 pHddSetBatchScanReq->rfBand = ucRfBand;
963 pHddSetBatchScanReq->rtt = nRtt;
964
Rajeev79dbe4c2013-10-05 11:03:42 +0530965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
966 "Received WLS_BATCHING_SET with SCANFREQ=%d "
967 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
968 pHddSetBatchScanReq->scanFrequency,
969 pHddSetBatchScanReq->numberOfScansToBatch,
970 pHddSetBatchScanReq->bestNetwork,
971 pHddSetBatchScanReq->rfBand,
972 pHddSetBatchScanReq->rtt);
973
974 return 0;
975}/*End of hdd_parse_set_batchscan_command*/
976
977/**---------------------------------------------------------------------------
978
979 \brief hdd_set_batch_scan_req_callback () - This function is called after
980 receiving set batch scan response from FW and it saves set batch scan
981 response data FW to HDD context and sets the completion event on
982 which hdd_ioctl is waiting
983
984 \param - callbackContext Pointer to HDD adapter
985 \param - pRsp Pointer to set batch scan response data received from FW
986
987 \return - nothing
988
989 --------------------------------------------------------------------------*/
990static void hdd_set_batch_scan_req_callback
991(
992 void *callbackContext,
993 tSirSetBatchScanRsp *pRsp
994)
995{
996 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
997 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
998
999 /*sanity check*/
1000 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1001 {
1002 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1003 "%s: Invalid pAdapter magic", __func__);
1004 VOS_ASSERT(0);
1005 return;
1006 }
1007 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1008
1009 /*save set batch scan response*/
1010 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1011
1012 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1013 "Received set batch scan rsp from FW with nScansToBatch=%d",
1014 pHddSetBatchScanRsp->nScansToBatch);
1015
1016 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1017 complete(&pAdapter->hdd_set_batch_scan_req_var);
1018
1019 return;
1020}/*End of hdd_set_batch_scan_req_callback*/
1021
1022
1023/**---------------------------------------------------------------------------
1024
1025 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1026 info in hdd batch scan response queue
1027
1028 \param - pAdapter Pointer to hdd adapter
1029 \param - pAPMetaInfo Pointer to access point meta info
1030 \param - scanId scan ID of batch scan response
1031 \param - isLastAp tells whether AP is last AP in batch scan response or not
1032
1033 \return - nothing
1034
1035 --------------------------------------------------------------------------*/
1036static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1037 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1038{
1039 tHddBatchScanRsp *pHead;
1040 tHddBatchScanRsp *pNode;
1041 tHddBatchScanRsp *pPrev;
1042 tHddBatchScanRsp *pTemp;
1043 tANI_U8 ssidLen;
1044
1045 /*head of hdd batch scan response queue*/
1046 pHead = pAdapter->pBatchScanRsp;
1047
1048 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1049 if (NULL == pNode)
1050 {
1051 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1052 "%s: Could not allocate memory", __func__);
1053 VOS_ASSERT(0);
1054 return;
1055 }
1056
1057 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1058 sizeof(pNode->ApInfo.bssid));
1059 ssidLen = strlen(pApMetaInfo->ssid);
1060 if (SIR_MAX_SSID_SIZE < ssidLen)
1061 {
1062 /*invalid scan result*/
1063 vos_mem_free(pNode);
1064 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1065 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1066 return;
1067 }
1068 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1069 /*null terminate ssid*/
1070 pNode->ApInfo.ssid[ssidLen] = '\0';
1071 pNode->ApInfo.ch = pApMetaInfo->ch;
1072 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1073 pNode->ApInfo.age = pApMetaInfo->timestamp;
1074 pNode->ApInfo.batchId = scanId;
1075 pNode->ApInfo.isLastAp = isLastAp;
1076
1077 pNode->pNext = NULL;
1078 if (NULL == pHead)
1079 {
1080 pAdapter->pBatchScanRsp = pNode;
1081 }
1082 else
1083 {
1084 pTemp = pHead;
1085 while (NULL != pTemp)
1086 {
1087 pPrev = pTemp;
1088 pTemp = pTemp->pNext;
1089 }
1090 pPrev->pNext = pNode;
1091 }
1092
1093 return;
1094}/*End of hdd_populate_batch_scan_rsp_queue*/
1095
1096/**---------------------------------------------------------------------------
1097
1098 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1099 receiving batch scan response indication from FW. It saves get batch scan
1100 response data in HDD batch scan response queue. This callback sets the
1101 completion event on which hdd_ioctl is waiting only after getting complete
1102 batch scan response data from FW
1103
1104 \param - callbackContext Pointer to HDD adapter
1105 \param - pRsp Pointer to get batch scan response data received from FW
1106
1107 \return - nothing
1108
1109 --------------------------------------------------------------------------*/
1110static void hdd_batch_scan_result_ind_callback
1111(
1112 void *callbackContext,
1113 void *pRsp
1114)
1115{
1116 v_BOOL_t isLastAp;
1117 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001118 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301119 tANI_U32 numberScanList;
1120 tANI_U32 nextScanListOffset;
1121 tANI_U32 nextApMetaInfoOffset;
1122 hdd_adapter_t* pAdapter;
1123 tpSirBatchScanList pScanList;
1124 tpSirBatchScanNetworkInfo pApMetaInfo;
1125 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1126 tSirSetBatchScanReq *pReq;
1127
1128 pAdapter = (hdd_adapter_t *)callbackContext;
1129 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001130 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301131 {
1132 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1133 "%s: Invalid pAdapter magic", __func__);
1134 VOS_ASSERT(0);
1135 return;
1136 }
1137
1138 /*initialize locals*/
1139 pReq = &pAdapter->hddSetBatchScanReq;
1140 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1141 isLastAp = FALSE;
1142 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001143 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301144 numberScanList = 0;
1145 nextScanListOffset = 0;
1146 nextApMetaInfoOffset = 0;
1147 pScanList = NULL;
1148 pApMetaInfo = NULL;
1149
1150 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1151 {
1152 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1153 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1154 isLastAp = TRUE;
1155 goto done;
1156 }
1157
1158 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1159 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1160 "Batch scan rsp: numberScalList %d", numberScanList);
1161
1162 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1163 {
1164 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1165 "%s: numberScanList %d", __func__, numberScanList);
1166 isLastAp = TRUE;
1167 goto done;
1168 }
1169
1170 while (numberScanList)
1171 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001172 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301173 nextScanListOffset);
1174 if (NULL == pScanList)
1175 {
1176 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1177 "%s: pScanList is %p", __func__, pScanList);
1178 isLastAp = TRUE;
1179 goto done;
1180 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001181 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301182 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001183 "Batch scan rsp: numApMetaInfo %d scanId %d",
1184 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301185
1186 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1187 {
1188 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1189 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1190 isLastAp = TRUE;
1191 goto done;
1192 }
1193
Rajeev Kumarce651e42013-10-21 18:57:15 -07001194 /*Initialize next AP meta info offset for next scan list*/
1195 nextApMetaInfoOffset = 0;
1196
Rajeev79dbe4c2013-10-05 11:03:42 +05301197 while (numApMetaInfo)
1198 {
1199 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1200 nextApMetaInfoOffset);
1201 if (NULL == pApMetaInfo)
1202 {
1203 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1204 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1205 isLastAp = TRUE;
1206 goto done;
1207 }
1208 /*calculate AP age*/
1209 pApMetaInfo->timestamp =
1210 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1211
1212 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001213 "%s: bssId "MAC_ADDRESS_STR
1214 " ch %d rssi %d timestamp %d", __func__,
1215 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1216 pApMetaInfo->ch, pApMetaInfo->rssi,
1217 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301218
1219 /*mark last AP in batch scan response*/
1220 if ((TRUE == pBatchScanRsp->isLastResult) &&
1221 (1 == numberScanList) && (1 == numApMetaInfo))
1222 {
1223 isLastAp = TRUE;
1224 }
1225
1226 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1227 /*store batch scan repsonse in hdd queue*/
1228 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1229 pScanList->scanId, isLastAp);
1230 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1231
1232 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1233 numApMetaInfo--;
1234 }
1235
Rajeev Kumarce651e42013-10-21 18:57:15 -07001236 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1237 + (sizeof(tSirBatchScanNetworkInfo)
1238 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301239 numberScanList--;
1240 }
1241
1242done:
1243
1244 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1245 requested from hdd_ioctl*/
1246 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1247 (TRUE == isLastAp))
1248 {
1249 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1250 complete(&pAdapter->hdd_get_batch_scan_req_var);
1251 }
1252
1253 return;
1254}/*End of hdd_batch_scan_result_ind_callback*/
1255
1256/**---------------------------------------------------------------------------
1257
1258 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1259 response as per batch scan FR request format by putting proper markers
1260
1261 \param - pDest pointer to destination buffer
1262 \param - cur_len current length
1263 \param - tot_len total remaining size which can be written to user space
1264 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1265 \param - pAdapter Pointer to HDD adapter
1266
1267 \return - ret no of characters written
1268
1269 --------------------------------------------------------------------------*/
1270static tANI_U32
1271hdd_format_batch_scan_rsp
1272(
1273 tANI_U8 *pDest,
1274 tANI_U32 cur_len,
1275 tANI_U32 tot_len,
1276 tHddBatchScanRsp *pApMetaInfo,
1277 hdd_adapter_t* pAdapter
1278)
1279{
1280 tANI_U32 ret = 0;
1281 tANI_U32 rem_len = 0;
1282 tANI_U8 temp_len = 0;
1283 tANI_U8 temp_total_len = 0;
1284 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1285 tANI_U8 *pTemp = temp;
1286
1287 /*Batch scan reponse needs to be returned to user space in
1288 following format:
1289 "scancount=X\n" where X is the number of scans in current batch
1290 batch
1291 "trunc\n" optional present if current scan truncated
1292 "bssid=XX:XX:XX:XX:XX:XX\n"
1293 "ssid=XXXX\n"
1294 "freq=X\n" frequency in Mhz
1295 "level=XX\n"
1296 "age=X\n" ms
1297 "dist=X\n" cm (-1 if not available)
1298 "errror=X\n" (-1if not available)
1299 "====\n" (end of ap marker)
1300 "####\n" (end of scan marker)
1301 "----\n" (end of results)*/
1302 /*send scan result in above format to user space based on
1303 available length*/
1304 /*The GET response may have more data than the driver can return in its
1305 buffer. In that case the buffer should be filled to the nearest complete
1306 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1307 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1308 The final buffer should end with "----\n"*/
1309
1310 /*sanity*/
1311 if (cur_len > tot_len)
1312 {
1313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1314 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1315 return 0;
1316 }
1317 else
1318 {
1319 rem_len = (tot_len - cur_len);
1320 }
1321
1322 /*end scan marker*/
1323 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1324 {
1325 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1326 pTemp += temp_len;
1327 temp_total_len += temp_len;
1328 }
1329
1330 /*bssid*/
1331 temp_len = snprintf(pTemp, sizeof(temp),
1332 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1333 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1334 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1335 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1336 pTemp += temp_len;
1337 temp_total_len += temp_len;
1338
1339 /*ssid*/
1340 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1341 pApMetaInfo->ApInfo.ssid);
1342 pTemp += temp_len;
1343 temp_total_len += temp_len;
1344
1345 /*freq*/
1346 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001347 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301348 pTemp += temp_len;
1349 temp_total_len += temp_len;
1350
1351 /*level*/
1352 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1353 pApMetaInfo->ApInfo.rssi);
1354 pTemp += temp_len;
1355 temp_total_len += temp_len;
1356
1357 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001358 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301359 pApMetaInfo->ApInfo.age);
1360 pTemp += temp_len;
1361 temp_total_len += temp_len;
1362
1363 /*dist*/
1364 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1365 pTemp += temp_len;
1366 temp_total_len += temp_len;
1367
1368 /*error*/
1369 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1370 pTemp += temp_len;
1371 temp_total_len += temp_len;
1372
1373 /*end AP marker*/
1374 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1375 pTemp += temp_len;
1376 temp_total_len += temp_len;
1377
1378 /*last AP in batch scan response*/
1379 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1380 {
1381 /*end scan marker*/
1382 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1383 pTemp += temp_len;
1384 temp_total_len += temp_len;
1385
1386 /*end batch scan result marker*/
1387 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1388 pTemp += temp_len;
1389 temp_total_len += temp_len;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08001390
1391 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301392 }
1393
1394 if (temp_total_len < rem_len)
1395 {
1396 ret = temp_total_len + 1;
1397 strlcpy(pDest, temp, ret);
1398 pAdapter->isTruncated = FALSE;
1399 }
1400 else
1401 {
1402 pAdapter->isTruncated = TRUE;
1403 if (rem_len >= strlen("%%%%"))
1404 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001405 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301406 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001407 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301408 {
1409 ret = 0;
1410 }
1411 }
1412
1413 return ret;
1414
1415}/*End of hdd_format_batch_scan_rsp*/
1416
1417/**---------------------------------------------------------------------------
1418
1419 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1420 buffer starting with head of hdd batch scan response queue
1421
1422 \param - pAdapter Pointer to HDD adapter
1423 \param - pDest Pointer to user data buffer
1424 \param - cur_len current offset in user buffer
1425 \param - rem_len remaining no of bytes in user buffer
1426
1427 \return - number of bytes written in user buffer
1428
1429 --------------------------------------------------------------------------*/
1430
1431tANI_U32 hdd_populate_user_batch_scan_rsp
1432(
1433 hdd_adapter_t* pAdapter,
1434 tANI_U8 *pDest,
1435 tANI_U32 cur_len,
1436 tANI_U32 rem_len
1437)
1438{
1439 tHddBatchScanRsp *pHead;
1440 tHddBatchScanRsp *pPrev;
1441 tANI_U32 len;
1442
Rajeev79dbe4c2013-10-05 11:03:42 +05301443 pAdapter->isTruncated = FALSE;
1444
1445 /*head of hdd batch scan response queue*/
1446 pHead = pAdapter->pBatchScanRsp;
1447 while (pHead)
1448 {
1449 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1450 pAdapter);
1451 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001452 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301453 cur_len += len;
1454 if(TRUE == pAdapter->isTruncated)
1455 {
1456 /*result is truncated return rest of scan rsp in next req*/
1457 cur_len = rem_len;
1458 break;
1459 }
1460 pPrev = pHead;
1461 pHead = pHead->pNext;
1462 pAdapter->pBatchScanRsp = pHead;
1463 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1464 vos_mem_free(pPrev);
1465 }
1466
1467 return cur_len;
1468}/*End of hdd_populate_user_batch_scan_rsp*/
1469
1470/**---------------------------------------------------------------------------
1471
1472 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1473 scan response data from HDD queue to user space
1474 It does following in detail:
1475 a) if HDD has enough data in its queue then it 1st copies data to user
1476 space and then send get batch scan indication message to FW. In this
1477 case it does not wait on any event and batch scan response data will
1478 be populated in HDD response queue in MC thread context after receiving
1479 indication from FW
1480 b) else send get batch scan indication message to FW and wait on an event
1481 which will be set once HDD receives complete batch scan response from
1482 FW and then this function returns batch scan response to user space
1483
1484 \param - pAdapter Pointer to HDD adapter
1485 \param - pPrivData Pointer to priv_data
1486
1487 \return - 0 for success -EFAULT for failure
1488
1489 --------------------------------------------------------------------------*/
1490
1491int hdd_return_batch_scan_rsp_to_user
1492(
1493 hdd_adapter_t* pAdapter,
1494 hdd_priv_data_t *pPrivData,
1495 tANI_U8 *command
1496)
1497{
1498 tANI_U8 *pDest;
1499 tANI_U32 count = 0;
1500 tANI_U32 len = 0;
1501 tANI_U32 cur_len = 0;
1502 tANI_U32 rem_len = 0;
1503 eHalStatus halStatus;
1504 unsigned long rc;
1505 tSirTriggerBatchScanResultInd *pReq;
1506
1507 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1508 pReq->param = 0;/*batch scan client*/
1509 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1510 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1511
1512 cur_len = pPrivData->used_len;
1513 if (pPrivData->total_len > pPrivData->used_len)
1514 {
1515 rem_len = pPrivData->total_len - pPrivData->used_len;
1516 }
1517 else
1518 {
1519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1520 "%s: Invalid user data buffer total_len %d used_len %d",
1521 __func__, pPrivData->total_len, pPrivData->used_len);
1522 return -EFAULT;
1523 }
1524
1525 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1526 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1527 cur_len, rem_len);
1528 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1529
1530 /*enough scan result available in cache to return to user space or
1531 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001532 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301533 {
1534 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1535 halStatus = sme_TriggerBatchScanResultInd(
1536 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1537 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1538 pAdapter);
1539 if ( eHAL_STATUS_SUCCESS == halStatus )
1540 {
1541 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1542 {
1543 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1544 rc = wait_for_completion_timeout(
1545 &pAdapter->hdd_get_batch_scan_req_var,
1546 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1547 if (0 == rc)
1548 {
1549 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1550 "%s: Timeout waiting to fetch batch scan rsp from fw",
1551 __func__);
1552 return -EFAULT;
1553 }
1554 }
1555
1556 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001557 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301558 pDest += len;
1559 cur_len += len;
1560
1561 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1562 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1563 cur_len, rem_len);
1564 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1565
1566 count = 0;
1567 len = (len - pPrivData->used_len);
1568 pDest = (command + pPrivData->used_len);
1569 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001570 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301571 while(count < len)
1572 {
1573 printk("%c", *(pDest + count));
1574 count++;
1575 }
1576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1577 "%s: copy %d data to user buffer", __func__, len);
1578 if (copy_to_user(pPrivData->buf, pDest, len))
1579 {
1580 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1581 "%s: failed to copy data to user buffer", __func__);
1582 return -EFAULT;
1583 }
1584 }
1585 else
1586 {
1587 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1588 "sme_GetBatchScanScan returned failure halStatus %d",
1589 halStatus);
1590 return -EINVAL;
1591 }
1592 }
1593 else
1594 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301595 count = 0;
1596 len = (len - pPrivData->used_len);
1597 pDest = (command + pPrivData->used_len);
1598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001599 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301600 while(count < len)
1601 {
1602 printk("%c", *(pDest + count));
1603 count++;
1604 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001605 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1606 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301607 if (copy_to_user(pPrivData->buf, pDest, len))
1608 {
1609 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1610 "%s: failed to copy data to user buffer", __func__);
1611 return -EFAULT;
1612 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301613 }
1614
1615 return 0;
1616} /*End of hdd_return_batch_scan_rsp_to_user*/
1617
1618#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1619
Jeff Johnson295189b2012-06-20 16:38:30 -07001620int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1621{
1622 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1623 hdd_priv_data_t priv_data;
1624 tANI_U8 *command = NULL;
1625 int ret = 0;
1626
1627 if (NULL == pAdapter)
1628 {
1629 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001630 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001631 ret = -ENODEV;
1632 goto exit;
1633 }
1634
Jeff Johnsone7245742012-09-05 17:12:55 -07001635 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001636 {
1637 ret = -EINVAL;
1638 goto exit;
1639 }
1640
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001641 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1642 {
1643 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1644 "%s:LOGP in Progress. Ignore!!!", __func__);
1645 ret = -EBUSY;
1646 goto exit;
1647 }
1648
Jeff Johnson295189b2012-06-20 16:38:30 -07001649 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1650 {
1651 ret = -EFAULT;
1652 goto exit;
1653 }
1654
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001655 if (priv_data.total_len <= 0)
1656 {
1657 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1658 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1659 priv_data.total_len);
1660 ret = -EINVAL;
1661 goto exit;
1662 }
1663
1664 /* Allocate +1 for '\0' */
1665 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001666 if (!command)
1667 {
1668 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001669 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001670 ret = -ENOMEM;
1671 goto exit;
1672 }
1673
1674 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1675 {
1676 ret = -EFAULT;
1677 goto exit;
1678 }
1679
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001680 /* Making sure the command is NUL-terminated */
1681 command[priv_data.total_len] = '\0';
1682
Jeff Johnson295189b2012-06-20 16:38:30 -07001683 if ((SIOCDEVPRIVATE + 1) == cmd)
1684 {
1685 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1686
1687 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001688 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001689
1690 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1691 {
1692 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1693 sizeof(tSirMacAddr)))
1694 {
1695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001696 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001697 ret = -EFAULT;
1698 }
1699 }
Amar Singhal0974e402013-02-12 14:27:46 -08001700 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001701 {
Amar Singhal0974e402013-02-12 14:27:46 -08001702 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001703 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001704
Jeff Johnson295189b2012-06-20 16:38:30 -07001705 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001706
1707 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001708 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001709 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001710 "%s: SetBandCommand Info comm %s UL %d, TL %d", __func__, command, priv_data.used_len, priv_data.total_len);
Jeff Johnson295189b2012-06-20 16:38:30 -07001711 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001712 ret = hdd_setBand_helper(dev, ptr);
1713 }
Kiet Lamf040f472013-11-20 21:15:23 +05301714 else if(strncmp(command, "SETWMMPS", 8) == 0)
1715 {
1716 tANI_U8 *ptr = command;
1717 ret = hdd_wmmps_helper(pAdapter, ptr);
1718 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001719 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1720 {
1721 char *country_code;
1722
1723 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001724
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001725 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001726 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001727#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301728 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001729#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001730 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1731 (void *)(tSmeChangeCountryCallback)
1732 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05301733 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001734 if (eHAL_STATUS_SUCCESS == ret)
1735 {
1736 ret = wait_for_completion_interruptible_timeout(
1737 &pAdapter->change_country_code,
1738 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1739 if (0 >= ret)
1740 {
1741 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1742 __func__);
1743 }
1744 }
1745 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001746 {
1747 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001748 "%s: SME Change Country code fail ret=%d", __func__, ret);
1749 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001750 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001751
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001752 }
1753 /*
1754 command should be a string having format
1755 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1756 */
Amar Singhal0974e402013-02-12 14:27:46 -08001757 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001758 {
Amar Singhal0974e402013-02-12 14:27:46 -08001759 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001760
1761 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001762 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001763
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001764 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001765 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001766 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1767 {
1768 int suspend = 0;
1769 tANI_U8 *ptr = (tANI_U8*)command + 15;
1770
1771 suspend = *ptr - '0';
1772 hdd_set_wlan_suspend_mode(suspend);
1773 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001774#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1775 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1776 {
1777 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001778 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001779 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1780 eHalStatus status = eHAL_STATUS_SUCCESS;
1781
1782 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1783 value = value + 15;
1784
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001785 /* Convert the value from ascii to integer */
1786 ret = kstrtos8(value, 10, &rssi);
1787 if (ret < 0)
1788 {
1789 /* If the input value is greater than max value of datatype, then also
1790 kstrtou8 fails */
1791 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1792 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001793 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001794 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1795 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1796 ret = -EINVAL;
1797 goto exit;
1798 }
1799
Srinivas Girigowdade697412013-02-14 16:31:48 -08001800 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001801
Srinivas Girigowdade697412013-02-14 16:31:48 -08001802 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1803 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1804 {
1805 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1806 "Neighbor lookup threshold value %d is out of range"
1807 " (Min: %d Max: %d)", lookUpThreshold,
1808 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1809 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1810 ret = -EINVAL;
1811 goto exit;
1812 }
1813
1814 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1815 "%s: Received Command to Set Roam trigger"
1816 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1817
1818 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1819 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1820 if (eHAL_STATUS_SUCCESS != status)
1821 {
1822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1823 "%s: Failed to set roam trigger, try again", __func__);
1824 ret = -EPERM;
1825 goto exit;
1826 }
1827
1828 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1829 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1830 }
1831 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1832 {
1833 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1834 int rssi = (-1) * lookUpThreshold;
1835 char extra[32];
1836 tANI_U8 len = 0;
1837
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001838 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001839 if (copy_to_user(priv_data.buf, &extra, len + 1))
1840 {
1841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1842 "%s: failed to copy data to user buffer", __func__);
1843 ret = -EFAULT;
1844 goto exit;
1845 }
1846 }
1847 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1848 {
1849 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001850 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001851 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001852
Srinivas Girigowdade697412013-02-14 16:31:48 -08001853 /* input refresh period is in terms of seconds */
1854 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1855 value = value + 18;
1856 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001857 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001858 if (ret < 0)
1859 {
1860 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001861 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001862 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001863 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001864 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001865 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1866 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001867 ret = -EINVAL;
1868 goto exit;
1869 }
1870
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001871 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1872 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001873 {
1874 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001875 "Roam scan period value %d is out of range"
1876 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001877 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1878 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001879 ret = -EINVAL;
1880 goto exit;
1881 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001882 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001883
1884 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1885 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001886 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001887
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001888 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1889 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001890 }
1891 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1892 {
1893 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1894 char extra[32];
1895 tANI_U8 len = 0;
1896
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001897 len = scnprintf(extra, sizeof(extra), "%s %d",
1898 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001899 /* Returned value is in units of seconds */
1900 if (copy_to_user(priv_data.buf, &extra, len + 1))
1901 {
1902 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1903 "%s: failed to copy data to user buffer", __func__);
1904 ret = -EFAULT;
1905 goto exit;
1906 }
1907 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001908 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1909 {
1910 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001911 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001912 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001913
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001914 /* input refresh period is in terms of seconds */
1915 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1916 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001917
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001918 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001919 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001920 if (ret < 0)
1921 {
1922 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001923 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001924 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001925 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001926 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001927 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1928 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1929 ret = -EINVAL;
1930 goto exit;
1931 }
1932
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001933 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1934 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1935 {
1936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1937 "Neighbor scan results refresh period value %d is out of range"
1938 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1939 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1940 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1941 ret = -EINVAL;
1942 goto exit;
1943 }
1944 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1945
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001946 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1947 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001948 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001949
1950 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1951 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1952 }
1953 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1954 {
1955 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1956 char extra[32];
1957 tANI_U8 len = 0;
1958
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001959 len = scnprintf(extra, sizeof(extra), "%s %d",
1960 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001961 /* Returned value is in units of seconds */
1962 if (copy_to_user(priv_data.buf, &extra, len + 1))
1963 {
1964 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1965 "%s: failed to copy data to user buffer", __func__);
1966 ret = -EFAULT;
1967 goto exit;
1968 }
1969 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001970#ifdef FEATURE_WLAN_LFR
1971 /* SETROAMMODE */
1972 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1973 {
1974 tANI_U8 *value = command;
1975 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1976
1977 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1978 value = value + SIZE_OF_SETROAMMODE + 1;
1979
1980 /* Convert the value from ascii to integer */
1981 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1982 if (ret < 0)
1983 {
1984 /* If the input value is greater than max value of datatype, then also
1985 kstrtou8 fails */
1986 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1987 "%s: kstrtou8 failed range [%d - %d]", __func__,
1988 CFG_LFR_FEATURE_ENABLED_MIN,
1989 CFG_LFR_FEATURE_ENABLED_MAX);
1990 ret = -EINVAL;
1991 goto exit;
1992 }
1993 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1994 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1995 {
1996 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1997 "Roam Mode value %d is out of range"
1998 " (Min: %d Max: %d)", roamMode,
1999 CFG_LFR_FEATURE_ENABLED_MIN,
2000 CFG_LFR_FEATURE_ENABLED_MAX);
2001 ret = -EINVAL;
2002 goto exit;
2003 }
2004
2005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2006 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2007 /*
2008 * Note that
2009 * SETROAMMODE 0 is to enable LFR while
2010 * SETROAMMODE 1 is to disable LFR, but
2011 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2012 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2013 */
2014 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2015 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2016 else
2017 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2018
2019 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2020 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2021 }
2022 /* GETROAMMODE */
2023 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2024 {
2025 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2026 char extra[32];
2027 tANI_U8 len = 0;
2028
2029 /*
2030 * roamMode value shall be inverted because the sementics is different.
2031 */
2032 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2033 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2034 else
2035 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2036
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002037 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002038 if (copy_to_user(priv_data.buf, &extra, len + 1))
2039 {
2040 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2041 "%s: failed to copy data to user buffer", __func__);
2042 ret = -EFAULT;
2043 goto exit;
2044 }
2045 }
2046#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002047#endif
2048#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2049 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2050 {
2051 tANI_U8 *value = command;
2052 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2053
2054 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2055 value = value + 13;
2056 /* Convert the value from ascii to integer */
2057 ret = kstrtou8(value, 10, &roamRssiDiff);
2058 if (ret < 0)
2059 {
2060 /* If the input value is greater than max value of datatype, then also
2061 kstrtou8 fails */
2062 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2063 "%s: kstrtou8 failed range [%d - %d]", __func__,
2064 CFG_ROAM_RSSI_DIFF_MIN,
2065 CFG_ROAM_RSSI_DIFF_MAX);
2066 ret = -EINVAL;
2067 goto exit;
2068 }
2069
2070 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2071 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2072 {
2073 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2074 "Roam rssi diff value %d is out of range"
2075 " (Min: %d Max: %d)", roamRssiDiff,
2076 CFG_ROAM_RSSI_DIFF_MIN,
2077 CFG_ROAM_RSSI_DIFF_MAX);
2078 ret = -EINVAL;
2079 goto exit;
2080 }
2081
2082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2083 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2084
2085 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2086 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2087 }
2088 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2089 {
2090 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2091 char extra[32];
2092 tANI_U8 len = 0;
2093
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002094 len = scnprintf(extra, sizeof(extra), "%s %d",
2095 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002096 if (copy_to_user(priv_data.buf, &extra, len + 1))
2097 {
2098 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2099 "%s: failed to copy data to user buffer", __func__);
2100 ret = -EFAULT;
2101 goto exit;
2102 }
2103 }
2104#endif
2105#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2106 else if (strncmp(command, "GETBAND", 7) == 0)
2107 {
2108 int band = -1;
2109 char extra[32];
2110 tANI_U8 len = 0;
2111 hdd_getBand_helper(pHddCtx, &band);
2112
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002113 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002114 if (copy_to_user(priv_data.buf, &extra, len + 1))
2115 {
2116 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2117 "%s: failed to copy data to user buffer", __func__);
2118 ret = -EFAULT;
2119 goto exit;
2120 }
2121 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002122 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2123 {
2124 tANI_U8 *value = command;
2125 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2126 tANI_U8 numChannels = 0;
2127 eHalStatus status = eHAL_STATUS_SUCCESS;
2128
2129 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2130 if (eHAL_STATUS_SUCCESS != status)
2131 {
2132 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2133 "%s: Failed to parse channel list information", __func__);
2134 ret = -EINVAL;
2135 goto exit;
2136 }
2137
2138 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2139 {
2140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2141 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2142 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2143 ret = -EINVAL;
2144 goto exit;
2145 }
2146 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2147 numChannels);
2148 if (eHAL_STATUS_SUCCESS != status)
2149 {
2150 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2151 "%s: Failed to update channel list information", __func__);
2152 ret = -EINVAL;
2153 goto exit;
2154 }
2155 }
2156 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2157 {
2158 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2159 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002160 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002161 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002162 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002163
2164 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2165 ChannelList, &numChannels ))
2166 {
2167 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2168 "%s: failed to get roam scan channel list", __func__);
2169 ret = -EFAULT;
2170 goto exit;
2171 }
2172 /* output channel list is of the format
2173 [Number of roam scan channels][Channel1][Channel2]... */
2174 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002175 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002176 for (j = 0; (j < numChannels); j++)
2177 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002178 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2179 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002180 }
2181
2182 if (copy_to_user(priv_data.buf, &extra, len + 1))
2183 {
2184 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2185 "%s: failed to copy data to user buffer", __func__);
2186 ret = -EFAULT;
2187 goto exit;
2188 }
2189 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002190 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2191 {
2192 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2193 char extra[32];
2194 tANI_U8 len = 0;
2195
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002196 /* Check if the features OKC/CCX/11R are supported simultaneously,
2197 then this operation is not permitted (return FAILURE) */
2198 if (ccxMode &&
2199 hdd_is_okc_mode_enabled(pHddCtx) &&
2200 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2201 {
2202 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2203 "%s: OKC/CCX/11R are supported simultaneously"
2204 " hence this operation is not permitted!", __func__);
2205 ret = -EPERM;
2206 goto exit;
2207 }
2208
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002209 len = scnprintf(extra, sizeof(extra), "%s %d",
2210 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002211 if (copy_to_user(priv_data.buf, &extra, len + 1))
2212 {
2213 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2214 "%s: failed to copy data to user buffer", __func__);
2215 ret = -EFAULT;
2216 goto exit;
2217 }
2218 }
2219 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2220 {
2221 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2222 char extra[32];
2223 tANI_U8 len = 0;
2224
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002225 /* Check if the features OKC/CCX/11R are supported simultaneously,
2226 then this operation is not permitted (return FAILURE) */
2227 if (okcMode &&
2228 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2229 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2230 {
2231 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2232 "%s: OKC/CCX/11R are supported simultaneously"
2233 " hence this operation is not permitted!", __func__);
2234 ret = -EPERM;
2235 goto exit;
2236 }
2237
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002238 len = scnprintf(extra, sizeof(extra), "%s %d",
2239 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002240 if (copy_to_user(priv_data.buf, &extra, len + 1))
2241 {
2242 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2243 "%s: failed to copy data to user buffer", __func__);
2244 ret = -EFAULT;
2245 goto exit;
2246 }
2247 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002248 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002249 {
2250 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2251 char extra[32];
2252 tANI_U8 len = 0;
2253
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002254 len = scnprintf(extra, sizeof(extra), "%s %d",
2255 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002256 if (copy_to_user(priv_data.buf, &extra, len + 1))
2257 {
2258 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2259 "%s: failed to copy data to user buffer", __func__);
2260 ret = -EFAULT;
2261 goto exit;
2262 }
2263 }
2264 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2265 {
2266 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2267 char extra[32];
2268 tANI_U8 len = 0;
2269
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002270 len = scnprintf(extra, sizeof(extra), "%s %d",
2271 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002272 if (copy_to_user(priv_data.buf, &extra, len + 1))
2273 {
2274 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2275 "%s: failed to copy data to user buffer", __func__);
2276 ret = -EFAULT;
2277 goto exit;
2278 }
2279 }
2280 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2281 {
2282 tANI_U8 *value = command;
2283 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2284
2285 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2286 value = value + 26;
2287 /* Convert the value from ascii to integer */
2288 ret = kstrtou8(value, 10, &minTime);
2289 if (ret < 0)
2290 {
2291 /* If the input value is greater than max value of datatype, then also
2292 kstrtou8 fails */
2293 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2294 "%s: kstrtou8 failed range [%d - %d]", __func__,
2295 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2296 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2297 ret = -EINVAL;
2298 goto exit;
2299 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002300 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2301 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2302 {
2303 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2304 "scan min channel time value %d is out of range"
2305 " (Min: %d Max: %d)", minTime,
2306 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2307 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2308 ret = -EINVAL;
2309 goto exit;
2310 }
2311
2312 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2313 "%s: Received Command to change channel min time = %d", __func__, minTime);
2314
2315 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2316 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2317 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002318 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2319 {
2320 tANI_U8 *value = command;
2321 tANI_U8 channel = 0;
2322 tANI_U8 dwellTime = 0;
2323 tANI_U8 bufLen = 0;
2324 tANI_U8 *buf = NULL;
2325 tSirMacAddr targetApBssid;
2326 eHalStatus status = eHAL_STATUS_SUCCESS;
2327 struct ieee80211_channel chan;
2328 tANI_U8 finalLen = 0;
2329 tANI_U8 *finalBuf = NULL;
2330 tANI_U8 temp = 0;
2331 u64 cookie;
2332 hdd_station_ctx_t *pHddStaCtx = NULL;
2333 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2334
2335 /* if not associated, no need to send action frame */
2336 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2337 {
2338 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2339 ret = -EINVAL;
2340 goto exit;
2341 }
2342
2343 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2344 &dwellTime, &buf, &bufLen);
2345 if (eHAL_STATUS_SUCCESS != status)
2346 {
2347 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2348 "%s: Failed to parse send action frame data", __func__);
2349 ret = -EINVAL;
2350 goto exit;
2351 }
2352
2353 /* if the target bssid is different from currently associated AP,
2354 then no need to send action frame */
2355 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2356 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2357 {
2358 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2359 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002360 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002361 goto exit;
2362 }
2363
2364 /* if the channel number is different from operating channel then
2365 no need to send action frame */
2366 if (channel != pHddStaCtx->conn_info.operationChannel)
2367 {
2368 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2369 "%s: channel(%d) is different from operating channel(%d)",
2370 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2371 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002372 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002373 goto exit;
2374 }
2375 chan.center_freq = sme_ChnToFreq(channel);
2376
2377 finalLen = bufLen + 24;
2378 finalBuf = vos_mem_malloc(finalLen);
2379 if (NULL == finalBuf)
2380 {
2381 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2382 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002383 vos_mem_free(buf);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002384 goto exit;
2385 }
2386 vos_mem_zero(finalBuf, finalLen);
2387
2388 /* Fill subtype */
2389 temp = SIR_MAC_MGMT_ACTION << 4;
2390 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2391
2392 /* Fill type */
2393 temp = SIR_MAC_MGMT_FRAME;
2394 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2395
2396 /* Fill destination address (bssid of the AP) */
2397 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2398
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002399 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002400 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2401
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002402 /* Fill BSSID (AP mac address) */
2403 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002404
2405 /* Fill received buffer from 24th address */
2406 vos_mem_copy(finalBuf + 24, buf, bufLen);
2407
Jeff Johnson11c33152013-04-16 17:52:40 -07002408 /* done with the parsed buffer */
2409 vos_mem_free(buf);
2410
Yue Maf49ba872013-08-19 12:04:25 -07002411 wlan_hdd_action( NULL,
2412#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2413 &(pAdapter->wdev),
2414#else
2415 dev,
2416#endif
2417 &chan, 0,
2418#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2419 NL80211_CHAN_HT20, 1,
2420#endif
2421 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002422 1, &cookie );
2423 vos_mem_free(finalBuf);
2424 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002425 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2426 {
2427 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2428 char extra[32];
2429 tANI_U8 len = 0;
2430
2431 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002432 len = scnprintf(extra, sizeof(extra), "%s %d",
2433 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002434 if (copy_to_user(priv_data.buf, &extra, len + 1))
2435 {
2436 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2437 "%s: failed to copy data to user buffer", __func__);
2438 ret = -EFAULT;
2439 goto exit;
2440 }
2441 }
2442 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2443 {
2444 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002445 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas 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) &&
Rajeev Kumar5286bb92013-12-05 11:52:10 -08003368 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
3369 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
Rajeev79dbe4c2013-10-05 11:03:42 +05303370 {
3371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003372 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303373 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3374 pAdapter->device_mode);
3375 ret = -EINVAL;
3376 goto exit;
3377 }
3378
Rajeev Kumar20140c12013-10-21 19:39:02 -07003379
Rajeev79dbe4c2013-10-05 11:03:42 +05303380 status = hdd_parse_set_batchscan_command(value, pReq);
3381 if (status)
3382 {
3383 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003384 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303385 ret = -EINVAL;
3386 goto exit;
3387 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003388
3389
Rajeev79dbe4c2013-10-05 11:03:42 +05303390 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3391 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3392 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3393 pAdapter);
3394
3395 if ( eHAL_STATUS_SUCCESS == halStatus )
3396 {
3397 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3398 "sme_SetBatchScanReq returned success halStatus %d",
3399 halStatus);
3400 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3401 {
3402 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3403 rc = wait_for_completion_timeout(
3404 &pAdapter->hdd_set_batch_scan_req_var,
3405 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3406 if (0 == rc)
3407 {
3408 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3409 "%s: Timeout waiting for set batch scan to complete",
3410 __func__);
3411 ret = -EINVAL;
3412 goto exit;
3413 }
3414 }
3415 if ( !pRsp->nScansToBatch )
3416 {
3417 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3418 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003419 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303420 ret = -EINVAL;
3421 goto exit;
3422 }
3423 /*As per the Batch Scan Framework API we should return the MIN of
3424 either MSCAN or the max # of scans firmware can cache*/
3425 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3426
Rajeev Kumar20140c12013-10-21 19:39:02 -07003427 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3428
Rajeev79dbe4c2013-10-05 11:03:42 +05303429 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3430 "%s: request MSCAN %d response MSCAN %d ret %d",
3431 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3432 }
3433 else
3434 {
3435 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3436 "sme_SetBatchScanReq returned failure halStatus %d",
3437 halStatus);
3438 ret = -EINVAL;
3439 goto exit;
3440 }
3441 }
3442 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3443 {
3444 eHalStatus halStatus;
3445 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3446 pInd->param = 0;
3447
3448 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3449 {
3450 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3451 "%s: Batch scan feature is not supported by FW", __func__);
3452 ret = -EINVAL;
3453 goto exit;
3454 }
3455
Rajeev Kumar20140c12013-10-21 19:39:02 -07003456 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303457 {
3458 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003459 "Batch scan is not yet enabled batch scan state %d",
3460 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303461 ret = -EINVAL;
3462 goto exit;
3463 }
3464
Rajeev Kumar20140c12013-10-21 19:39:02 -07003465 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3466
Rajeev79dbe4c2013-10-05 11:03:42 +05303467 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3468 pAdapter->sessionId);
3469 if ( eHAL_STATUS_SUCCESS == halStatus )
3470 {
3471 ret = 0;
3472 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3473 "sme_StopBatchScanInd returned success halStatus %d",
3474 halStatus);
3475 }
3476 else
3477 {
3478 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3479 "sme_StopBatchScanInd returned failure halStatus %d",
3480 halStatus);
3481 ret = -EINVAL;
3482 goto exit;
3483 }
3484 }
3485 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3486 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003487 tANI_U32 remain_len;
3488
Rajeev79dbe4c2013-10-05 11:03:42 +05303489 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3490 {
3491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3492 "%s: Batch scan feature is not supported by FW", __func__);
3493 ret = -EINVAL;
3494 goto exit;
3495 }
3496
Rajeev Kumar20140c12013-10-21 19:39:02 -07003497 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303498 {
3499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003500 "Batch scan is not yet enabled could not return results"
3501 "Batch Scan state %d",
3502 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303503 ret = -EINVAL;
3504 goto exit;
3505 }
3506
3507 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003508 remain_len = priv_data.total_len - priv_data.used_len;
3509 if (remain_len < priv_data.total_len)
3510 {
3511 /*Clear previous batch scan response data if any*/
3512 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3513 }
3514 else
3515 {
3516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3517 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003518 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003519 priv_data.total_len, priv_data.used_len, remain_len);
3520 ret = -EINVAL;
3521 goto exit;
3522 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303523 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3524 }
3525#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003526#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3527 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3528 {
3529 tANI_U8 *value = command;
3530 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3531 tANI_U8 numChannels = 0;
3532 eHalStatus status = eHAL_STATUS_SUCCESS;
3533
3534 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3535 if (eHAL_STATUS_SUCCESS != status)
3536 {
3537 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3538 "%s: Failed to parse channel list information", __func__);
3539 ret = -EINVAL;
3540 goto exit;
3541 }
3542
3543 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3544 {
3545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3546 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3547 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3548 ret = -EINVAL;
3549 goto exit;
3550 }
3551 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3552 ChannelList,
3553 numChannels);
3554 if (eHAL_STATUS_SUCCESS != status)
3555 {
3556 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3557 "%s: Failed to update channel list information", __func__);
3558 ret = -EINVAL;
3559 goto exit;
3560 }
3561 }
3562 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3563 {
3564 tANI_U8 *value = command;
3565 char extra[128] = {0};
3566 int len = 0;
3567 tANI_U8 tid = 0;
3568 hdd_station_ctx_t *pHddStaCtx = NULL;
3569 tAniTrafStrmMetrics tsmMetrics;
3570 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3571
3572 /* if not associated, return error */
3573 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3574 {
3575 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3576 ret = -EINVAL;
3577 goto exit;
3578 }
3579
3580 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3581 value = value + 12;
3582 /* Convert the value from ascii to integer */
3583 ret = kstrtou8(value, 10, &tid);
3584 if (ret < 0)
3585 {
3586 /* If the input value is greater than max value of datatype, then also
3587 kstrtou8 fails */
3588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3589 "%s: kstrtou8 failed range [%d - %d]", __func__,
3590 TID_MIN_VALUE,
3591 TID_MAX_VALUE);
3592 ret = -EINVAL;
3593 goto exit;
3594 }
3595
3596 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3597 {
3598 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3599 "tid value %d is out of range"
3600 " (Min: %d Max: %d)", tid,
3601 TID_MIN_VALUE,
3602 TID_MAX_VALUE);
3603 ret = -EINVAL;
3604 goto exit;
3605 }
3606
3607 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3608 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3609
3610 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3611 {
3612 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3613 "%s: failed to get tsm stats", __func__);
3614 ret = -EFAULT;
3615 goto exit;
3616 }
3617
3618 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3619 "UplinkPktQueueDly(%d)\n"
3620 "UplinkPktQueueDlyHist[0](%d)\n"
3621 "UplinkPktQueueDlyHist[1](%d)\n"
3622 "UplinkPktQueueDlyHist[2](%d)\n"
3623 "UplinkPktQueueDlyHist[3](%d)\n"
3624 "UplinkPktTxDly(%lu)\n"
3625 "UplinkPktLoss(%d)\n"
3626 "UplinkPktCount(%d)\n"
3627 "RoamingCount(%d)\n"
3628 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3629 tsmMetrics.UplinkPktQueueDlyHist[0],
3630 tsmMetrics.UplinkPktQueueDlyHist[1],
3631 tsmMetrics.UplinkPktQueueDlyHist[2],
3632 tsmMetrics.UplinkPktQueueDlyHist[3],
3633 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3634 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3635
3636 /* Output TSM stats is of the format
3637 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3638 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003639 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003640 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3641 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3642 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3643 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3644 tsmMetrics.RoamingDly);
3645
3646 if (copy_to_user(priv_data.buf, &extra, len + 1))
3647 {
3648 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3649 "%s: failed to copy data to user buffer", __func__);
3650 ret = -EFAULT;
3651 goto exit;
3652 }
3653 }
3654 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3655 {
3656 tANI_U8 *value = command;
3657 tANI_U8 *cckmIe = NULL;
3658 tANI_U8 cckmIeLen = 0;
3659 eHalStatus status = eHAL_STATUS_SUCCESS;
3660
3661 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3662 if (eHAL_STATUS_SUCCESS != status)
3663 {
3664 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3665 "%s: Failed to parse cckm ie data", __func__);
3666 ret = -EINVAL;
3667 goto exit;
3668 }
3669
3670 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3671 {
3672 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3673 "%s: CCKM Ie input length is more than max[%d]", __func__,
3674 DOT11F_IE_RSN_MAX_LEN);
3675 if (NULL != cckmIe)
3676 {
3677 vos_mem_free(cckmIe);
3678 }
3679 ret = -EINVAL;
3680 goto exit;
3681 }
3682 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
3683 if (NULL != cckmIe)
3684 {
3685 vos_mem_free(cckmIe);
3686 }
3687 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003688 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3689 {
3690 tANI_U8 *value = command;
3691 tCsrCcxBeaconReq ccxBcnReq;
3692 eHalStatus status = eHAL_STATUS_SUCCESS;
3693 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3694 if (eHAL_STATUS_SUCCESS != status)
3695 {
3696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3697 "%s: Failed to parse ccx beacon req", __func__);
3698 ret = -EINVAL;
3699 goto exit;
3700 }
3701
3702 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3703 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003704#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003705 else {
3706 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3707 __func__, command);
3708 }
3709
Jeff Johnson295189b2012-06-20 16:38:30 -07003710 }
3711exit:
3712 if (command)
3713 {
3714 kfree(command);
3715 }
3716 return ret;
3717}
3718
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003719
3720
3721#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003722/**---------------------------------------------------------------------------
3723
3724 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3725
3726 This function parses the ccx beacon request passed in the format
3727 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3728 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3729 <space>Scan Mode N<space>Meas Duration N
3730 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3731 then take N.
3732 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3733 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3734 This function does not take care of removing duplicate channels from the list
3735
3736 \param - pValue Pointer to data
3737 \param - pCcxBcnReq output pointer to store parsed ie information
3738
3739 \return - 0 for success non-zero for failure
3740
3741 --------------------------------------------------------------------------*/
3742static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3743 tCsrCcxBeaconReq *pCcxBcnReq)
3744{
3745 tANI_U8 *inPtr = pValue;
3746 int tempInt = 0;
3747 int j = 0, i = 0, v = 0;
3748 char buf[32];
3749
3750 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3751 /*no argument after the command*/
3752 if (NULL == inPtr)
3753 {
3754 return -EINVAL;
3755 }
3756 /*no space after the command*/
3757 else if (SPACE_ASCII_VALUE != *inPtr)
3758 {
3759 return -EINVAL;
3760 }
3761
3762 /*removing empty spaces*/
3763 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3764
3765 /*no argument followed by spaces*/
3766 if ('\0' == *inPtr) return -EINVAL;
3767
3768 /*getting the first argument ie measurement token*/
3769 v = sscanf(inPtr, "%32s ", buf);
3770 if (1 != v) return -EINVAL;
3771
3772 v = kstrtos32(buf, 10, &tempInt);
3773 if ( v < 0) return -EINVAL;
3774
3775 pCcxBcnReq->numBcnReqIe = tempInt;
3776
3777 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3778 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3779
3780 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3781 {
3782 for (i = 0; i < 4; i++)
3783 {
3784 /*inPtr pointing to the beginning of first space after number of ie fields*/
3785 inPtr = strpbrk( inPtr, " " );
3786 /*no ie data after the number of ie fields argument*/
3787 if (NULL == inPtr) return -EINVAL;
3788
3789 /*removing empty space*/
3790 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3791
3792 /*no ie data after the number of ie fields argument and spaces*/
3793 if ( '\0' == *inPtr ) return -EINVAL;
3794
3795 v = sscanf(inPtr, "%32s ", buf);
3796 if (1 != v) return -EINVAL;
3797
3798 v = kstrtos32(buf, 10, &tempInt);
3799 if (v < 0) return -EINVAL;
3800
3801 switch (i)
3802 {
3803 case 0: /* Measurement token */
3804 if (tempInt <= 0)
3805 {
3806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3807 "Invalid Measurement Token(%d)", tempInt);
3808 return -EINVAL;
3809 }
3810 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3811 break;
3812
3813 case 1: /* Channel number */
3814 if ((tempInt <= 0) ||
3815 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3816 {
3817 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3818 "Invalid Channel Number(%d)", tempInt);
3819 return -EINVAL;
3820 }
3821 pCcxBcnReq->bcnReq[j].channel = tempInt;
3822 break;
3823
3824 case 2: /* Scan mode */
3825 if ((tempInt < 0) || (tempInt > 2))
3826 {
3827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3828 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3829 return -EINVAL;
3830 }
3831 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3832 break;
3833
3834 case 3: /* Measurement duration */
3835 if (tempInt <= 0)
3836 {
3837 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3838 "Invalid Measurement Duration(%d)", tempInt);
3839 return -EINVAL;
3840 }
3841 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3842 break;
3843 }
3844 }
3845 }
3846
3847 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3848 {
3849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3850 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3851 j,
3852 pCcxBcnReq->bcnReq[j].measurementToken,
3853 pCcxBcnReq->bcnReq[j].channel,
3854 pCcxBcnReq->bcnReq[j].scanMode,
3855 pCcxBcnReq->bcnReq[j].measurementDuration);
3856 }
3857
3858 return VOS_STATUS_SUCCESS;
3859}
3860
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003861static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3862{
3863 struct statsContext *pStatsContext = NULL;
3864 hdd_adapter_t *pAdapter = NULL;
3865
3866 if (NULL == pContext)
3867 {
3868 hddLog(VOS_TRACE_LEVEL_ERROR,
3869 "%s: Bad param, pContext [%p]",
3870 __func__, pContext);
3871 return;
3872 }
3873
3874 /* there is a race condition that exists between this callback function
3875 and the caller since the caller could time out either before or
3876 while this code is executing. we'll assume the timeout hasn't
3877 occurred, but we'll verify that right before we save our work */
3878
3879 pStatsContext = pContext;
3880 pAdapter = pStatsContext->pAdapter;
3881 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3882 {
3883 /* the caller presumably timed out so there is nothing we can do */
3884 hddLog(VOS_TRACE_LEVEL_WARN,
3885 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3886 __func__, pAdapter, pStatsContext->magic);
3887 return;
3888 }
3889
3890 /* the race is on. caller could have timed out immediately after
3891 we verified the magic, but if so, caller will wait a short time
3892 for us to copy over the tsm stats */
3893 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3894 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3895 tsmMetrics.UplinkPktQueueDlyHist,
3896 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3897 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3898 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3899 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3900 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3901 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3902 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3903
3904 /* and notify the caller */
3905 complete(&pStatsContext->completion);
3906}
3907
3908
3909
3910static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3911 tAniTrafStrmMetrics* pTsmMetrics)
3912{
3913 hdd_station_ctx_t *pHddStaCtx = NULL;
3914 eHalStatus hstatus;
3915 long lrc;
3916 struct statsContext context;
3917 hdd_context_t *pHddCtx = NULL;
3918
3919 if (NULL == pAdapter)
3920 {
3921 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3922 return VOS_STATUS_E_FAULT;
3923 }
3924
3925 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3926 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3927
3928 /* we are connected prepare our callback context */
3929 init_completion(&context.completion);
3930 context.pAdapter = pAdapter;
3931 context.magic = STATS_CONTEXT_MAGIC;
3932
3933 /* query tsm stats */
3934 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3935 pHddStaCtx->conn_info.staId[ 0 ],
3936 pHddStaCtx->conn_info.bssId,
3937 &context, pHddCtx->pvosContext, tid);
3938
3939 if (eHAL_STATUS_SUCCESS != hstatus)
3940 {
3941 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3942 return hstatus;
3943 }
3944 else
3945 {
3946 /* request was sent -- wait for the response */
3947 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3948 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3949 /* either we have a response or we timed out
3950 either way, first invalidate our magic */
3951 context.magic = 0;
3952 if (lrc <= 0)
3953 {
3954 hddLog(VOS_TRACE_LEVEL_ERROR,
3955 "%s: SME %s while retrieving statistics",
3956 __func__, (0 == lrc) ? "timeout" : "interrupt");
3957 /* there is a race condition such that the callback
3958 function could be executing at the same time we are. of
3959 primary concern is if the callback function had already
3960 verified the "magic" but hasn't yet set the completion
3961 variable. Since the completion variable is on our
3962 stack, we'll delay just a bit to make sure the data is
3963 still valid if that is the case */
3964 msleep(50);
3965 return (VOS_STATUS_E_TIMEOUT);
3966 }
3967 }
3968 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3969 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3970 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3971 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3972 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3973 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3974 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3975 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3976 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3977 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3978
3979 return VOS_STATUS_SUCCESS;
3980}
3981#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3982
Srinivas Girigowdade697412013-02-14 16:31:48 -08003983#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3984void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3985{
3986 eCsrBand band = -1;
3987 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3988 switch (band)
3989 {
3990 case eCSR_BAND_ALL:
3991 *pBand = WLAN_HDD_UI_BAND_AUTO;
3992 break;
3993
3994 case eCSR_BAND_24:
3995 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3996 break;
3997
3998 case eCSR_BAND_5G:
3999 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4000 break;
4001
4002 default:
4003 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4004 *pBand = -1;
4005 break;
4006 }
4007}
4008
4009/**---------------------------------------------------------------------------
4010
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004011 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4012
4013 This function parses the send action frame data passed in the format
4014 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4015
Srinivas Girigowda56076852013-08-20 14:00:50 -07004016 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004017 \param - pTargetApBssid Pointer to target Ap bssid
4018 \param - pChannel Pointer to the Target AP channel
4019 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4020 \param - pBuf Pointer to data
4021 \param - pBufLen Pointer to data length
4022
4023 \return - 0 for success non-zero for failure
4024
4025 --------------------------------------------------------------------------*/
4026VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4027 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4028{
4029 tANI_U8 *inPtr = pValue;
4030 tANI_U8 *dataEnd;
4031 int tempInt;
4032 int j = 0;
4033 int i = 0;
4034 int v = 0;
4035 tANI_U8 tempBuf[32];
4036 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004037 /* 12 hexa decimal digits and 5 ':' */
4038 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004039
4040 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4041 /*no argument after the command*/
4042 if (NULL == inPtr)
4043 {
4044 return -EINVAL;
4045 }
4046
4047 /*no space after the command*/
4048 else if (SPACE_ASCII_VALUE != *inPtr)
4049 {
4050 return -EINVAL;
4051 }
4052
4053 /*removing empty spaces*/
4054 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4055
4056 /*no argument followed by spaces*/
4057 if ('\0' == *inPtr)
4058 {
4059 return -EINVAL;
4060 }
4061
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004062 v = sscanf(inPtr, "%17s", macAddress);
4063 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004064 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4066 "Invalid MAC address or All hex inputs are not read (%d)", v);
4067 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004068 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004069
4070 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4071 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4072 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4073 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4074 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4075 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004076
4077 /* point to the next argument */
4078 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4079 /*no argument after the command*/
4080 if (NULL == inPtr) return -EINVAL;
4081
4082 /*removing empty spaces*/
4083 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4084
4085 /*no argument followed by spaces*/
4086 if ('\0' == *inPtr)
4087 {
4088 return -EINVAL;
4089 }
4090
4091 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004092 v = sscanf(inPtr, "%32s ", tempBuf);
4093 if (1 != v) return -EINVAL;
4094
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004095 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304096 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4097 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004098
4099 *pChannel = tempInt;
4100
4101 /* point to the next argument */
4102 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4103 /*no argument after the command*/
4104 if (NULL == inPtr) return -EINVAL;
4105 /*removing empty spaces*/
4106 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4107
4108 /*no argument followed by spaces*/
4109 if ('\0' == *inPtr)
4110 {
4111 return -EINVAL;
4112 }
4113
4114 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004115 v = sscanf(inPtr, "%32s ", tempBuf);
4116 if (1 != v) return -EINVAL;
4117
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004118 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304119 if ( v < 0 || tempInt <= 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004120
4121 *pDwellTime = tempInt;
4122
4123 /* point to the next argument */
4124 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4125 /*no argument after the command*/
4126 if (NULL == inPtr) return -EINVAL;
4127 /*removing empty spaces*/
4128 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4129
4130 /*no argument followed by spaces*/
4131 if ('\0' == *inPtr)
4132 {
4133 return -EINVAL;
4134 }
4135
4136 /* find the length of data */
4137 dataEnd = inPtr;
4138 while(('\0' != *dataEnd) )
4139 {
4140 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004141 }
Kiet Lambe150c22013-11-21 16:30:32 +05304142 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004143 if ( *pBufLen <= 0) return -EINVAL;
4144
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004145 /* Allocate the number of bytes based on the number of input characters
4146 whether it is even or odd.
4147 if the number of input characters are even, then we need N/2 byte.
4148 if the number of input characters are odd, then we need do (N+1)/2 to
4149 compensate rounding off.
4150 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4151 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4152 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004153 if (NULL == *pBuf)
4154 {
4155 hddLog(VOS_TRACE_LEVEL_FATAL,
4156 "%s: vos_mem_alloc failed ", __func__);
4157 return -EINVAL;
4158 }
4159
4160 /* the buffer received from the upper layer is character buffer,
4161 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4162 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4163 and f0 in 3rd location */
4164 for (i = 0, j = 0; j < *pBufLen; j += 2)
4165 {
Kiet Lambe150c22013-11-21 16:30:32 +05304166 if( j+1 == *pBufLen)
4167 {
4168 tempByte = hdd_parse_hex(inPtr[j]);
4169 }
4170 else
4171 {
4172 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4173 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004174 (*pBuf)[i++] = tempByte;
4175 }
4176 *pBufLen = i;
4177 return VOS_STATUS_SUCCESS;
4178}
4179
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004180/**---------------------------------------------------------------------------
4181
Srinivas Girigowdade697412013-02-14 16:31:48 -08004182 \brief hdd_parse_channellist() - HDD Parse channel list
4183
4184 This function parses the channel list passed in the format
4185 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004186 if the Number of channels (N) does not match with the actual number of channels passed
4187 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4188 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4189 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4190 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004191
4192 \param - pValue Pointer to input channel list
4193 \param - ChannelList Pointer to local output array to record channel list
4194 \param - pNumChannels Pointer to number of roam scan channels
4195
4196 \return - 0 for success non-zero for failure
4197
4198 --------------------------------------------------------------------------*/
4199VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4200{
4201 tANI_U8 *inPtr = pValue;
4202 int tempInt;
4203 int j = 0;
4204 int v = 0;
4205 char buf[32];
4206
4207 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4208 /*no argument after the command*/
4209 if (NULL == inPtr)
4210 {
4211 return -EINVAL;
4212 }
4213
4214 /*no space after the command*/
4215 else if (SPACE_ASCII_VALUE != *inPtr)
4216 {
4217 return -EINVAL;
4218 }
4219
4220 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004221 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004222
4223 /*no argument followed by spaces*/
4224 if ('\0' == *inPtr)
4225 {
4226 return -EINVAL;
4227 }
4228
4229 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004230 v = sscanf(inPtr, "%32s ", buf);
4231 if (1 != v) return -EINVAL;
4232
Srinivas Girigowdade697412013-02-14 16:31:48 -08004233 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004234 if ((v < 0) ||
4235 (tempInt <= 0) ||
4236 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4237 {
4238 return -EINVAL;
4239 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004240
4241 *pNumChannels = tempInt;
4242
4243 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4244 "Number of channels are: %d", *pNumChannels);
4245
4246 for (j = 0; j < (*pNumChannels); j++)
4247 {
4248 /*inPtr pointing to the beginning of first space after number of channels*/
4249 inPtr = strpbrk( inPtr, " " );
4250 /*no channel list after the number of channels argument*/
4251 if (NULL == inPtr)
4252 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004253 if (0 != j)
4254 {
4255 *pNumChannels = j;
4256 return VOS_STATUS_SUCCESS;
4257 }
4258 else
4259 {
4260 return -EINVAL;
4261 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004262 }
4263
4264 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004265 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004266
4267 /*no channel list after the number of channels argument and spaces*/
4268 if ( '\0' == *inPtr )
4269 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004270 if (0 != j)
4271 {
4272 *pNumChannels = j;
4273 return VOS_STATUS_SUCCESS;
4274 }
4275 else
4276 {
4277 return -EINVAL;
4278 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004279 }
4280
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004281 v = sscanf(inPtr, "%32s ", buf);
4282 if (1 != v) return -EINVAL;
4283
Srinivas Girigowdade697412013-02-14 16:31:48 -08004284 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004285 if ((v < 0) ||
4286 (tempInt <= 0) ||
4287 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4288 {
4289 return -EINVAL;
4290 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004291 pChannelList[j] = tempInt;
4292
4293 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4294 "Channel %d added to preferred channel list",
4295 pChannelList[j] );
4296 }
4297
Srinivas Girigowdade697412013-02-14 16:31:48 -08004298 return VOS_STATUS_SUCCESS;
4299}
4300
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004301
4302/**---------------------------------------------------------------------------
4303
4304 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4305
4306 This function parses the reasoc command data passed in the format
4307 REASSOC<space><bssid><space><channel>
4308
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004309 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004310 \param - pTargetApBssid Pointer to target Ap bssid
4311 \param - pChannel Pointer to the Target AP channel
4312
4313 \return - 0 for success non-zero for failure
4314
4315 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004316VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4317 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004318{
4319 tANI_U8 *inPtr = pValue;
4320 int tempInt;
4321 int v = 0;
4322 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004323 /* 12 hexa decimal digits and 5 ':' */
4324 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004325
4326 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4327 /*no argument after the command*/
4328 if (NULL == inPtr)
4329 {
4330 return -EINVAL;
4331 }
4332
4333 /*no space after the command*/
4334 else if (SPACE_ASCII_VALUE != *inPtr)
4335 {
4336 return -EINVAL;
4337 }
4338
4339 /*removing empty spaces*/
4340 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4341
4342 /*no argument followed by spaces*/
4343 if ('\0' == *inPtr)
4344 {
4345 return -EINVAL;
4346 }
4347
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004348 v = sscanf(inPtr, "%17s", macAddress);
4349 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004350 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004351 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4352 "Invalid MAC address or All hex inputs are not read (%d)", v);
4353 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004354 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004355
4356 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4357 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4358 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4359 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4360 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4361 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004362
4363 /* point to the next argument */
4364 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4365 /*no argument after the command*/
4366 if (NULL == inPtr) return -EINVAL;
4367
4368 /*removing empty spaces*/
4369 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4370
4371 /*no argument followed by spaces*/
4372 if ('\0' == *inPtr)
4373 {
4374 return -EINVAL;
4375 }
4376
4377 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004378 v = sscanf(inPtr, "%32s ", tempBuf);
4379 if (1 != v) return -EINVAL;
4380
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004381 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004382 if ((v < 0) ||
4383 (tempInt <= 0) ||
4384 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4385 {
4386 return -EINVAL;
4387 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004388
4389 *pChannel = tempInt;
4390 return VOS_STATUS_SUCCESS;
4391}
4392
4393#endif
4394
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004395#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4396/**---------------------------------------------------------------------------
4397
4398 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4399
4400 This function parses the SETCCKM IE command
4401 SETCCKMIE<space><ie data>
4402
4403 \param - pValue Pointer to input data
4404 \param - pCckmIe Pointer to output cckm Ie
4405 \param - pCckmIeLen Pointer to output cckm ie length
4406
4407 \return - 0 for success non-zero for failure
4408
4409 --------------------------------------------------------------------------*/
4410VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4411 tANI_U8 *pCckmIeLen)
4412{
4413 tANI_U8 *inPtr = pValue;
4414 tANI_U8 *dataEnd;
4415 int j = 0;
4416 int i = 0;
4417 tANI_U8 tempByte = 0;
4418
4419 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4420 /*no argument after the command*/
4421 if (NULL == inPtr)
4422 {
4423 return -EINVAL;
4424 }
4425
4426 /*no space after the command*/
4427 else if (SPACE_ASCII_VALUE != *inPtr)
4428 {
4429 return -EINVAL;
4430 }
4431
4432 /*removing empty spaces*/
4433 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4434
4435 /*no argument followed by spaces*/
4436 if ('\0' == *inPtr)
4437 {
4438 return -EINVAL;
4439 }
4440
4441 /* find the length of data */
4442 dataEnd = inPtr;
4443 while(('\0' != *dataEnd) )
4444 {
4445 dataEnd++;
4446 ++(*pCckmIeLen);
4447 }
4448 if ( *pCckmIeLen <= 0) return -EINVAL;
4449
4450 /* Allocate the number of bytes based on the number of input characters
4451 whether it is even or odd.
4452 if the number of input characters are even, then we need N/2 byte.
4453 if the number of input characters are odd, then we need do (N+1)/2 to
4454 compensate rounding off.
4455 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4456 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4457 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4458 if (NULL == *pCckmIe)
4459 {
4460 hddLog(VOS_TRACE_LEVEL_FATAL,
4461 "%s: vos_mem_alloc failed ", __func__);
4462 return -EINVAL;
4463 }
4464 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4465 /* the buffer received from the upper layer is character buffer,
4466 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4467 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4468 and f0 in 3rd location */
4469 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4470 {
4471 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4472 (*pCckmIe)[i++] = tempByte;
4473 }
4474 *pCckmIeLen = i;
4475
4476 return VOS_STATUS_SUCCESS;
4477}
4478#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4479
Jeff Johnson295189b2012-06-20 16:38:30 -07004480/**---------------------------------------------------------------------------
4481
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004482 \brief hdd_is_valid_mac_address() - Validate MAC address
4483
4484 This function validates whether the given MAC address is valid or not
4485 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4486 where X is the hexa decimal digit character and separated by ':'
4487 This algorithm works even if MAC address is not separated by ':'
4488
4489 This code checks given input string mac contains exactly 12 hexadecimal digits.
4490 and a separator colon : appears in the input string only after
4491 an even number of hex digits.
4492
4493 \param - pMacAddr pointer to the input MAC address
4494 \return - 1 for valid and 0 for invalid
4495
4496 --------------------------------------------------------------------------*/
4497
4498v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4499{
4500 int xdigit = 0;
4501 int separator = 0;
4502 while (*pMacAddr)
4503 {
4504 if (isxdigit(*pMacAddr))
4505 {
4506 xdigit++;
4507 }
4508 else if (':' == *pMacAddr)
4509 {
4510 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4511 break;
4512
4513 ++separator;
4514 }
4515 else
4516 {
4517 separator = -1;
4518 /* Invalid MAC found */
4519 return 0;
4520 }
4521 ++pMacAddr;
4522 }
4523 return (xdigit == 12 && (separator == 5 || separator == 0));
4524}
4525
4526/**---------------------------------------------------------------------------
4527
Jeff Johnson295189b2012-06-20 16:38:30 -07004528 \brief hdd_open() - HDD Open function
4529
4530 This is called in response to ifconfig up
4531
4532 \param - dev Pointer to net_device structure
4533
4534 \return - 0 for success non-zero for failure
4535
4536 --------------------------------------------------------------------------*/
4537int hdd_open (struct net_device *dev)
4538{
4539 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4540 hdd_context_t *pHddCtx;
4541 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4542 VOS_STATUS status;
4543 v_BOOL_t in_standby = TRUE;
4544
4545 if (NULL == pAdapter)
4546 {
4547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004548 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004549 return -ENODEV;
4550 }
4551
4552 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4553 if (NULL == pHddCtx)
4554 {
4555 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004556 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004557 return -ENODEV;
4558 }
4559
4560 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4561 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4562 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004563 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4564 {
4565 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304566 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004567 in_standby = FALSE;
4568 break;
4569 }
4570 else
4571 {
4572 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4573 pAdapterNode = pNext;
4574 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004575 }
4576
4577 if (TRUE == in_standby)
4578 {
4579 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4580 {
4581 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4582 "wlan out of power save", __func__);
4583 return -EINVAL;
4584 }
4585 }
4586
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004587 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004588 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4589 {
4590 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004591 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004592 /* Enable TX queues only when we are connected */
4593 netif_tx_start_all_queues(dev);
4594 }
4595
4596 return 0;
4597}
4598
4599int hdd_mon_open (struct net_device *dev)
4600{
4601 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4602
4603 if(pAdapter == NULL) {
4604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004605 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004606 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004607 }
4608
4609 netif_start_queue(dev);
4610
4611 return 0;
4612}
4613/**---------------------------------------------------------------------------
4614
4615 \brief hdd_stop() - HDD stop function
4616
4617 This is called in response to ifconfig down
4618
4619 \param - dev Pointer to net_device structure
4620
4621 \return - 0 for success non-zero for failure
4622
4623 --------------------------------------------------------------------------*/
4624
4625int hdd_stop (struct net_device *dev)
4626{
4627 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4628 hdd_context_t *pHddCtx;
4629 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4630 VOS_STATUS status;
4631 v_BOOL_t enter_standby = TRUE;
4632
4633 ENTER();
4634
4635 if (NULL == pAdapter)
4636 {
4637 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004638 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004639 return -ENODEV;
4640 }
4641
4642 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4643 if (NULL == pHddCtx)
4644 {
4645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004646 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004647 return -ENODEV;
4648 }
4649
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004650 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004651 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4652 netif_tx_disable(pAdapter->dev);
4653 netif_carrier_off(pAdapter->dev);
4654
4655
4656 /* SoftAP ifaces should never go in power save mode
4657 making sure same here. */
4658 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4659 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004660 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004661 )
4662 {
4663 /* SoftAP mode, so return from here */
4664 EXIT();
4665 return 0;
4666 }
4667
4668 /* Find if any iface is up then
4669 if any iface is up then can't put device to sleep/ power save mode. */
4670 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4671 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4672 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004673 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4674 {
4675 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304676 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004677 enter_standby = FALSE;
4678 break;
4679 }
4680 else
4681 {
4682 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4683 pAdapterNode = pNext;
4684 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004685 }
4686
4687 if (TRUE == enter_standby)
4688 {
4689 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4690 "entering standby", __func__);
4691 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4692 {
4693 /*log and return success*/
4694 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4695 "wlan in power save", __func__);
4696 }
4697 }
4698
4699 EXIT();
4700 return 0;
4701}
4702
4703/**---------------------------------------------------------------------------
4704
4705 \brief hdd_uninit() - HDD uninit function
4706
4707 This is called during the netdev unregister to uninitialize all data
4708associated with the device
4709
4710 \param - dev Pointer to net_device structure
4711
4712 \return - void
4713
4714 --------------------------------------------------------------------------*/
4715static void hdd_uninit (struct net_device *dev)
4716{
4717 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4718
4719 ENTER();
4720
4721 do
4722 {
4723 if (NULL == pAdapter)
4724 {
4725 hddLog(VOS_TRACE_LEVEL_FATAL,
4726 "%s: NULL pAdapter", __func__);
4727 break;
4728 }
4729
4730 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4731 {
4732 hddLog(VOS_TRACE_LEVEL_FATAL,
4733 "%s: Invalid magic", __func__);
4734 break;
4735 }
4736
4737 if (NULL == pAdapter->pHddCtx)
4738 {
4739 hddLog(VOS_TRACE_LEVEL_FATAL,
4740 "%s: NULL pHddCtx", __func__);
4741 break;
4742 }
4743
4744 if (dev != pAdapter->dev)
4745 {
4746 hddLog(VOS_TRACE_LEVEL_FATAL,
4747 "%s: Invalid device reference", __func__);
4748 /* we haven't validated all cases so let this go for now */
4749 }
4750
4751 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4752
4753 /* after uninit our adapter structure will no longer be valid */
4754 pAdapter->dev = NULL;
4755 pAdapter->magic = 0;
4756 } while (0);
4757
4758 EXIT();
4759}
4760
4761/**---------------------------------------------------------------------------
4762
4763 \brief hdd_release_firmware() -
4764
4765 This function calls the release firmware API to free the firmware buffer.
4766
4767 \param - pFileName Pointer to the File Name.
4768 pCtx - Pointer to the adapter .
4769
4770
4771 \return - 0 for success, non zero for failure
4772
4773 --------------------------------------------------------------------------*/
4774
4775VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4776{
4777 VOS_STATUS status = VOS_STATUS_SUCCESS;
4778 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4779 ENTER();
4780
4781
4782 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4783
4784 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4785
4786 if(pHddCtx->fw) {
4787 release_firmware(pHddCtx->fw);
4788 pHddCtx->fw = NULL;
4789 }
4790 else
4791 status = VOS_STATUS_E_FAILURE;
4792 }
4793 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4794 if(pHddCtx->nv) {
4795 release_firmware(pHddCtx->nv);
4796 pHddCtx->nv = NULL;
4797 }
4798 else
4799 status = VOS_STATUS_E_FAILURE;
4800
4801 }
4802
4803 EXIT();
4804 return status;
4805}
4806
4807/**---------------------------------------------------------------------------
4808
4809 \brief hdd_request_firmware() -
4810
4811 This function reads the firmware file using the request firmware
4812 API and returns the the firmware data and the firmware file size.
4813
4814 \param - pfileName - Pointer to the file name.
4815 - pCtx - Pointer to the adapter .
4816 - ppfw_data - Pointer to the pointer of the firmware data.
4817 - pSize - Pointer to the file size.
4818
4819 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4820
4821 --------------------------------------------------------------------------*/
4822
4823
4824VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4825{
4826 int status;
4827 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4828 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4829 ENTER();
4830
4831 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4832
4833 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4834
4835 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4836 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4837 __func__, pfileName);
4838 retval = VOS_STATUS_E_FAILURE;
4839 }
4840
4841 else {
4842 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4843 *pSize = pHddCtx->fw->size;
4844 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4845 __func__, *pSize);
4846 }
4847 }
4848 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4849
4850 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4851
4852 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4853 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4854 __func__, pfileName);
4855 retval = VOS_STATUS_E_FAILURE;
4856 }
4857
4858 else {
4859 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4860 *pSize = pHddCtx->nv->size;
4861 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4862 __func__, *pSize);
4863 }
4864 }
4865
4866 EXIT();
4867 return retval;
4868}
4869/**---------------------------------------------------------------------------
4870 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4871
4872 This is the function invoked by SME to inform the result of a full power
4873 request issued by HDD
4874
4875 \param - callbackcontext - Pointer to cookie
4876 status - result of request
4877
4878 \return - None
4879
4880--------------------------------------------------------------------------*/
4881void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4882{
4883 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4884
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004885 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004886 if(&pHddCtx->full_pwr_comp_var)
4887 {
4888 complete(&pHddCtx->full_pwr_comp_var);
4889 }
4890}
4891
4892/**---------------------------------------------------------------------------
4893
4894 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4895
4896 This is the function invoked by SME to inform the result of BMPS
4897 request issued by HDD
4898
4899 \param - callbackcontext - Pointer to cookie
4900 status - result of request
4901
4902 \return - None
4903
4904--------------------------------------------------------------------------*/
4905void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4906{
4907
4908 struct completion *completion_var = (struct completion*) callbackContext;
4909
Arif Hussain6d2a3322013-11-17 19:50:10 -08004910 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004911 if(completion_var != NULL)
4912 {
4913 complete(completion_var);
4914 }
4915}
4916
4917/**---------------------------------------------------------------------------
4918
4919 \brief hdd_get_cfg_file_size() -
4920
4921 This function reads the configuration file using the request firmware
4922 API and returns the configuration file size.
4923
4924 \param - pCtx - Pointer to the adapter .
4925 - pFileName - Pointer to the file name.
4926 - pBufSize - Pointer to the buffer size.
4927
4928 \return - 0 for success, non zero for failure
4929
4930 --------------------------------------------------------------------------*/
4931
4932VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4933{
4934 int status;
4935 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4936
4937 ENTER();
4938
4939 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4940
4941 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4942 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4943 status = VOS_STATUS_E_FAILURE;
4944 }
4945 else {
4946 *pBufSize = pHddCtx->fw->size;
4947 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4948 release_firmware(pHddCtx->fw);
4949 pHddCtx->fw = NULL;
4950 }
4951
4952 EXIT();
4953 return VOS_STATUS_SUCCESS;
4954}
4955
4956/**---------------------------------------------------------------------------
4957
4958 \brief hdd_read_cfg_file() -
4959
4960 This function reads the configuration file using the request firmware
4961 API and returns the cfg data and the buffer size of the configuration file.
4962
4963 \param - pCtx - Pointer to the adapter .
4964 - pFileName - Pointer to the file name.
4965 - pBuffer - Pointer to the data buffer.
4966 - pBufSize - Pointer to the buffer size.
4967
4968 \return - 0 for success, non zero for failure
4969
4970 --------------------------------------------------------------------------*/
4971
4972VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4973 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4974{
4975 int status;
4976 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4977
4978 ENTER();
4979
4980 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4981
4982 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4983 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4984 return VOS_STATUS_E_FAILURE;
4985 }
4986 else {
4987 if(*pBufSize != pHddCtx->fw->size) {
4988 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4989 "file size", __func__);
4990 release_firmware(pHddCtx->fw);
4991 pHddCtx->fw = NULL;
4992 return VOS_STATUS_E_FAILURE;
4993 }
4994 else {
4995 if(pBuffer) {
4996 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4997 }
4998 release_firmware(pHddCtx->fw);
4999 pHddCtx->fw = NULL;
5000 }
5001 }
5002
5003 EXIT();
5004
5005 return VOS_STATUS_SUCCESS;
5006}
5007
5008/**---------------------------------------------------------------------------
5009
Jeff Johnson295189b2012-06-20 16:38:30 -07005010 \brief hdd_set_mac_address() -
5011
5012 This function sets the user specified mac address using
5013 the command ifconfig wlanX hw ether <mac adress>.
5014
5015 \param - dev - Pointer to the net device.
5016 - addr - Pointer to the sockaddr.
5017 \return - 0 for success, non zero for failure
5018
5019 --------------------------------------------------------------------------*/
5020
5021static int hdd_set_mac_address(struct net_device *dev, void *addr)
5022{
5023 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5024 struct sockaddr *psta_mac_addr = addr;
5025 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5026
5027 ENTER();
5028
5029 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5030
5031#ifdef HDD_SESSIONIZE
5032 // set the MAC address though the STA ID CFG.
5033 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5034 (v_U8_t *)&pAdapter->macAddressCurrent,
5035 sizeof( pAdapter->macAddressCurrent ),
5036 hdd_set_mac_addr_cb, VOS_FALSE );
5037#endif
5038
5039 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5040
5041 EXIT();
5042 return halStatus;
5043}
5044
5045tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5046{
5047 int i;
5048 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5049 {
5050 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5051 break;
5052 }
5053
5054 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5055 return NULL;
5056
5057 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5058 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5059}
5060
5061void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5062{
5063 int i;
5064 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5065 {
5066 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5067 {
5068 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5069 break;
5070 }
5071 }
5072 return;
5073}
5074
5075#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5076 static struct net_device_ops wlan_drv_ops = {
5077 .ndo_open = hdd_open,
5078 .ndo_stop = hdd_stop,
5079 .ndo_uninit = hdd_uninit,
5080 .ndo_start_xmit = hdd_hard_start_xmit,
5081 .ndo_tx_timeout = hdd_tx_timeout,
5082 .ndo_get_stats = hdd_stats,
5083 .ndo_do_ioctl = hdd_ioctl,
5084 .ndo_set_mac_address = hdd_set_mac_address,
5085 .ndo_select_queue = hdd_select_queue,
5086#ifdef WLAN_FEATURE_PACKET_FILTERING
5087#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5088 .ndo_set_rx_mode = hdd_set_multicast_list,
5089#else
5090 .ndo_set_multicast_list = hdd_set_multicast_list,
5091#endif //LINUX_VERSION_CODE
5092#endif
5093 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005094 static struct net_device_ops wlan_mon_drv_ops = {
5095 .ndo_open = hdd_mon_open,
5096 .ndo_stop = hdd_stop,
5097 .ndo_uninit = hdd_uninit,
5098 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5099 .ndo_tx_timeout = hdd_tx_timeout,
5100 .ndo_get_stats = hdd_stats,
5101 .ndo_do_ioctl = hdd_ioctl,
5102 .ndo_set_mac_address = hdd_set_mac_address,
5103 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005104
5105#endif
5106
5107void hdd_set_station_ops( struct net_device *pWlanDev )
5108{
5109#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005110 pWlanDev->netdev_ops = &wlan_drv_ops;
5111#else
5112 pWlanDev->open = hdd_open;
5113 pWlanDev->stop = hdd_stop;
5114 pWlanDev->uninit = hdd_uninit;
5115 pWlanDev->hard_start_xmit = NULL;
5116 pWlanDev->tx_timeout = hdd_tx_timeout;
5117 pWlanDev->get_stats = hdd_stats;
5118 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005119 pWlanDev->set_mac_address = hdd_set_mac_address;
5120#endif
5121}
5122
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005123static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005124{
5125 struct net_device *pWlanDev = NULL;
5126 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005127 /*
5128 * cfg80211 initialization and registration....
5129 */
5130 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5131
Jeff Johnson295189b2012-06-20 16:38:30 -07005132 if(pWlanDev != NULL)
5133 {
5134
5135 //Save the pointer to the net_device in the HDD adapter
5136 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5137
Jeff Johnson295189b2012-06-20 16:38:30 -07005138 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5139
5140 pAdapter->dev = pWlanDev;
5141 pAdapter->pHddCtx = pHddCtx;
5142 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5143
5144 init_completion(&pAdapter->session_open_comp_var);
5145 init_completion(&pAdapter->session_close_comp_var);
5146 init_completion(&pAdapter->disconnect_comp_var);
5147 init_completion(&pAdapter->linkup_event_var);
5148 init_completion(&pAdapter->cancel_rem_on_chan_var);
5149 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005150#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5151 init_completion(&pAdapter->offchannel_tx_event);
5152#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005153 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005154#ifdef FEATURE_WLAN_TDLS
5155 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005156 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005157 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305158 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005159#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005160 init_completion(&pHddCtx->mc_sus_event_var);
5161 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305162 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005163 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005164 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005165
Rajeev79dbe4c2013-10-05 11:03:42 +05305166#ifdef FEATURE_WLAN_BATCH_SCAN
5167 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5168 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5169 pAdapter->pBatchScanRsp = NULL;
5170 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005171 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08005172 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305173 mutex_init(&pAdapter->hdd_batch_scan_lock);
5174#endif
5175
Jeff Johnson295189b2012-06-20 16:38:30 -07005176 pAdapter->isLinkUpSvcNeeded = FALSE;
5177 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5178 //Init the net_device structure
5179 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5180
5181 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5182 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5183 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5184 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5185
5186 hdd_set_station_ops( pAdapter->dev );
5187
5188 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005189 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5190 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5191 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005192 /* set pWlanDev's parent to underlying device */
5193 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5194 }
5195
5196 return pAdapter;
5197}
5198
5199VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5200{
5201 struct net_device *pWlanDev = pAdapter->dev;
5202 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5203 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5204 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5205
5206 if( rtnl_lock_held )
5207 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005208 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5210 {
5211 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5212 return VOS_STATUS_E_FAILURE;
5213 }
5214 }
5215 if (register_netdevice(pWlanDev))
5216 {
5217 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5218 return VOS_STATUS_E_FAILURE;
5219 }
5220 }
5221 else
5222 {
5223 if(register_netdev(pWlanDev))
5224 {
5225 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5226 return VOS_STATUS_E_FAILURE;
5227 }
5228 }
5229 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5230
5231 return VOS_STATUS_SUCCESS;
5232}
5233
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005234static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005235{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005236 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005237
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005238 if (NULL == pAdapter)
5239 {
5240 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5241 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005242 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005243
5244 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5245 {
5246 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5247 return eHAL_STATUS_NOT_INITIALIZED;
5248 }
5249
5250 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5251
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005252#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005253 /* need to make sure all of our scheduled work has completed.
5254 * This callback is called from MC thread context, so it is safe to
5255 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005256 *
5257 * Even though this is called from MC thread context, if there is a faulty
5258 * work item in the system, that can hang this call forever. So flushing
5259 * this global work queue is not safe; and now we make sure that
5260 * individual work queues are stopped correctly. But the cancel work queue
5261 * is a GPL only API, so the proprietary version of the driver would still
5262 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005263 */
5264 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005265#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005266
5267 /* We can be blocked while waiting for scheduled work to be
5268 * flushed, and the adapter structure can potentially be freed, in
5269 * which case the magic will have been reset. So make sure the
5270 * magic is still good, and hence the adapter structure is still
5271 * valid, before signaling completion */
5272 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5273 {
5274 complete(&pAdapter->session_close_comp_var);
5275 }
5276
Jeff Johnson295189b2012-06-20 16:38:30 -07005277 return eHAL_STATUS_SUCCESS;
5278}
5279
5280VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5281{
5282 struct net_device *pWlanDev = pAdapter->dev;
5283 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5284 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5285 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5286 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5287 int rc = 0;
5288
5289 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005290 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005291 //Open a SME session for future operation
5292 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005293 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005294 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5295 {
5296 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005297 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005298 halStatus, halStatus );
5299 status = VOS_STATUS_E_FAILURE;
5300 goto error_sme_open;
5301 }
5302
5303 //Block on a completion variable. Can't wait forever though.
5304 rc = wait_for_completion_interruptible_timeout(
5305 &pAdapter->session_open_comp_var,
5306 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5307 if (!rc)
5308 {
5309 hddLog(VOS_TRACE_LEVEL_FATAL,
5310 "Session is not opened within timeout period code %08d", rc );
5311 status = VOS_STATUS_E_FAILURE;
5312 goto error_sme_open;
5313 }
5314
5315 // Register wireless extensions
5316 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5317 {
5318 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005319 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005320 halStatus, halStatus );
5321 status = VOS_STATUS_E_FAILURE;
5322 goto error_register_wext;
5323 }
5324 //Safe to register the hard_start_xmit function again
5325#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5326 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5327#else
5328 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5329#endif
5330
5331 //Set the Connection State to Not Connected
5332 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5333
5334 //Set the default operation channel
5335 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5336
5337 /* Make the default Auth Type as OPEN*/
5338 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5339
5340 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5341 {
5342 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005343 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005344 status, status );
5345 goto error_init_txrx;
5346 }
5347
5348 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5349
5350 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5351 {
5352 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005353 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005354 status, status );
5355 goto error_wmm_init;
5356 }
5357
5358 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5359
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005360#ifdef FEATURE_WLAN_TDLS
5361 if(0 != wlan_hdd_tdls_init(pAdapter))
5362 {
5363 status = VOS_STATUS_E_FAILURE;
5364 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5365 goto error_tdls_init;
5366 }
5367 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5368#endif
5369
Jeff Johnson295189b2012-06-20 16:38:30 -07005370 return VOS_STATUS_SUCCESS;
5371
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005372#ifdef FEATURE_WLAN_TDLS
5373error_tdls_init:
5374 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5375 hdd_wmm_adapter_close(pAdapter);
5376#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005377error_wmm_init:
5378 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5379 hdd_deinit_tx_rx(pAdapter);
5380error_init_txrx:
5381 hdd_UnregisterWext(pWlanDev);
5382error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005383 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005384 {
5385 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005386 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005387 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005388 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005389 {
5390 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005391 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005392 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005393 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005394 }
5395}
5396error_sme_open:
5397 return status;
5398}
5399
Jeff Johnson295189b2012-06-20 16:38:30 -07005400void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5401{
5402 hdd_cfg80211_state_t *cfgState;
5403
5404 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5405
5406 if( NULL != cfgState->buf )
5407 {
5408 int rc;
5409 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5410 rc = wait_for_completion_interruptible_timeout(
5411 &pAdapter->tx_action_cnf_event,
5412 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5413 if(!rc)
5414 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005415 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005416 ("ERROR: HDD Wait for Action Confirmation Failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07005417 }
5418 }
5419 return;
5420}
Jeff Johnson295189b2012-06-20 16:38:30 -07005421
5422void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5423{
5424 ENTER();
5425 switch ( pAdapter->device_mode )
5426 {
5427 case WLAN_HDD_INFRA_STATION:
5428 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005429 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005430 {
5431 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5432 {
5433 hdd_deinit_tx_rx( pAdapter );
5434 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5435 }
5436
5437 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5438 {
5439 hdd_wmm_adapter_close( pAdapter );
5440 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5441 }
5442
Jeff Johnson295189b2012-06-20 16:38:30 -07005443 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005444#ifdef FEATURE_WLAN_TDLS
5445 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5446 {
5447 wlan_hdd_tdls_exit(pAdapter);
5448 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5449 }
5450#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005451
5452 break;
5453 }
5454
5455 case WLAN_HDD_SOFTAP:
5456 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005457 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305458
5459 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5460 {
5461 hdd_wmm_adapter_close( pAdapter );
5462 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5463 }
5464
Jeff Johnson295189b2012-06-20 16:38:30 -07005465 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005466
5467 hdd_unregister_hostapd(pAdapter);
5468 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005469 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005470 break;
5471 }
5472
5473 case WLAN_HDD_MONITOR:
5474 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005475 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005476 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5477 {
5478 hdd_deinit_tx_rx( pAdapter );
5479 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5480 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005481 if(NULL != pAdapterforTx)
5482 {
5483 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5484 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005485 break;
5486 }
5487
5488
5489 default:
5490 break;
5491 }
5492
5493 EXIT();
5494}
5495
5496void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5497{
5498 struct net_device *pWlanDev = pAdapter->dev;
5499
Rajeev79dbe4c2013-10-05 11:03:42 +05305500#ifdef FEATURE_WLAN_BATCH_SCAN
5501 tHddBatchScanRsp *pNode;
5502 tHddBatchScanRsp *pPrev;
5503 if (pAdapter)
5504 {
5505 mutex_lock(&pAdapter->hdd_batch_scan_lock);
5506 pNode = pAdapter->pBatchScanRsp;
5507 while (pNode)
5508 {
5509 pPrev = pNode;
5510 pNode = pNode->pNext;
5511 vos_mem_free((v_VOID_t * )pPrev);
5512 }
5513 pAdapter->pBatchScanRsp = NULL;
5514 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
5515 }
5516#endif
5517
Jeff Johnson295189b2012-06-20 16:38:30 -07005518 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5519 if( rtnl_held )
5520 {
5521 unregister_netdevice(pWlanDev);
5522 }
5523 else
5524 {
5525 unregister_netdev(pWlanDev);
5526 }
5527 // note that the pAdapter is no longer valid at this point
5528 // since the memory has been reclaimed
5529 }
5530
5531}
5532
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005533void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5534{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305535 VOS_STATUS status;
5536 hdd_adapter_t *pAdapter = NULL;
5537 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005538
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305539 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005540
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305541 /*loop through all adapters.*/
5542 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005543 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305544 pAdapter = pAdapterNode->pAdapter;
5545 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5546 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005547
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305548 { // we skip this registration for modes other than STA and P2P client modes.
5549 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5550 pAdapterNode = pNext;
5551 continue;
5552 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005553
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305554 //Apply Dynamic DTIM For P2P
5555 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5556 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5557 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5558 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5559 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5560 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5561 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5562 (eConnectionState_Associated ==
5563 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5564 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5565 {
5566 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005567
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305568 powerRequest.uIgnoreDTIM = 1;
5569 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5570
5571 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5572 {
5573 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5574 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5575 }
5576 else
5577 {
5578 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5579 }
5580
5581 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5582 * specified during Enter/Exit BMPS when LCD off*/
5583 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5584 NULL, eANI_BOOLEAN_FALSE);
5585 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5586 NULL, eANI_BOOLEAN_FALSE);
5587
5588 /* switch to the DTIM specified in cfg.ini */
5589 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5590 "Switch to DTIM %d", powerRequest.uListenInterval);
5591 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5592 break;
5593
5594 }
5595
5596 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5597 pAdapterNode = pNext;
5598 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005599}
5600
5601void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5602{
5603 /*Switch back to DTIM 1*/
5604 tSirSetPowerParamsReq powerRequest = { 0 };
5605
5606 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5607 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005608 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005609
5610 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5611 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5612 NULL, eANI_BOOLEAN_FALSE);
5613 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5614 NULL, eANI_BOOLEAN_FALSE);
5615
5616 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5617 "Switch to DTIM%d",powerRequest.uListenInterval);
5618 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5619
5620}
5621
Jeff Johnson295189b2012-06-20 16:38:30 -07005622VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5623{
5624 VOS_STATUS status = VOS_STATUS_SUCCESS;
5625
5626 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5627 {
5628 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5629 }
5630
5631 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5632 {
5633 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5634 }
5635
5636 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5637 {
5638 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5639 }
5640
5641 return status;
5642}
5643
5644VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5645{
5646 hdd_adapter_t *pAdapter = NULL;
5647 eHalStatus halStatus;
5648 VOS_STATUS status = VOS_STATUS_E_INVAL;
5649 v_BOOL_t disableBmps = FALSE;
5650 v_BOOL_t disableImps = FALSE;
5651
5652 switch(session_type)
5653 {
5654 case WLAN_HDD_INFRA_STATION:
5655 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005656 case WLAN_HDD_P2P_CLIENT:
5657 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005658 //Exit BMPS -> Is Sta/P2P Client is already connected
5659 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5660 if((NULL != pAdapter)&&
5661 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5662 {
5663 disableBmps = TRUE;
5664 }
5665
5666 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5667 if((NULL != pAdapter)&&
5668 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5669 {
5670 disableBmps = TRUE;
5671 }
5672
5673 //Exit both Bmps and Imps incase of Go/SAP Mode
5674 if((WLAN_HDD_SOFTAP == session_type) ||
5675 (WLAN_HDD_P2P_GO == session_type))
5676 {
5677 disableBmps = TRUE;
5678 disableImps = TRUE;
5679 }
5680
5681 if(TRUE == disableImps)
5682 {
5683 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5684 {
5685 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5686 }
5687 }
5688
5689 if(TRUE == disableBmps)
5690 {
5691 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5692 {
5693 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5694
5695 if(eHAL_STATUS_SUCCESS != halStatus)
5696 {
5697 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005698 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005699 VOS_ASSERT(0);
5700 return status;
5701 }
5702 }
5703
5704 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5705 {
5706 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5707
5708 if(eHAL_STATUS_SUCCESS != halStatus)
5709 {
5710 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005711 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005712 VOS_ASSERT(0);
5713 return status;
5714 }
5715 }
5716 }
5717
5718 if((TRUE == disableBmps) ||
5719 (TRUE == disableImps))
5720 {
5721 /* Now, get the chip into Full Power now */
5722 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5723 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5724 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5725
5726 if(halStatus != eHAL_STATUS_SUCCESS)
5727 {
5728 if(halStatus == eHAL_STATUS_PMC_PENDING)
5729 {
5730 //Block on a completion variable. Can't wait forever though
5731 wait_for_completion_interruptible_timeout(
5732 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5733 }
5734 else
5735 {
5736 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005737 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005738 VOS_ASSERT(0);
5739 return status;
5740 }
5741 }
5742
5743 status = VOS_STATUS_SUCCESS;
5744 }
5745
5746 break;
5747 }
5748 return status;
5749}
5750
5751hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005752 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005753 tANI_U8 rtnl_held )
5754{
5755 hdd_adapter_t *pAdapter = NULL;
5756 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5757 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5758 VOS_STATUS exitbmpsStatus;
5759
Arif Hussain6d2a3322013-11-17 19:50:10 -08005760 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005761
5762 //Disable BMPS incase of Concurrency
5763 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5764
5765 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5766 {
5767 //Fail to Exit BMPS
5768 VOS_ASSERT(0);
5769 return NULL;
5770 }
5771
5772 switch(session_type)
5773 {
5774 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005775 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005776 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005777 {
5778 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5779
5780 if( NULL == pAdapter )
5781 return NULL;
5782
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305783#ifdef FEATURE_WLAN_TDLS
5784 /* A Mutex Lock is introduced while changing/initializing the mode to
5785 * protect the concurrent access for the Adapters by TDLS module.
5786 */
5787 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5788 {
5789 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5790 "%s: unable to lock list", __func__);
5791 return NULL;
5792 }
5793#endif
5794
Jeff Johnsone7245742012-09-05 17:12:55 -07005795 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5796 NL80211_IFTYPE_P2P_CLIENT:
5797 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005798
Jeff Johnson295189b2012-06-20 16:38:30 -07005799 pAdapter->device_mode = session_type;
5800
5801 status = hdd_init_station_mode( pAdapter );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305802#ifdef FEATURE_WLAN_TDLS
5803 mutex_unlock(&pHddCtx->tdls_lock);
5804#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005805 if( VOS_STATUS_SUCCESS != status )
5806 goto err_free_netdev;
5807
5808 status = hdd_register_interface( pAdapter, rtnl_held );
5809 if( VOS_STATUS_SUCCESS != status )
5810 {
5811 hdd_deinit_adapter(pHddCtx, pAdapter);
5812 goto err_free_netdev;
5813 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305814
5815#ifdef WLAN_NS_OFFLOAD
5816 // Workqueue which gets scheduled in IPv6 notification callback.
5817 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5818#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005819 //Stop the Interface TX queue.
5820 netif_tx_disable(pAdapter->dev);
5821 //netif_tx_disable(pWlanDev);
5822 netif_carrier_off(pAdapter->dev);
5823
5824 break;
5825 }
5826
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005828 case WLAN_HDD_SOFTAP:
5829 {
5830 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5831 if( NULL == pAdapter )
5832 return NULL;
5833
Jeff Johnson295189b2012-06-20 16:38:30 -07005834 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5835 NL80211_IFTYPE_AP:
5836 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005837 pAdapter->device_mode = session_type;
5838
5839 status = hdd_init_ap_mode(pAdapter);
5840 if( VOS_STATUS_SUCCESS != status )
5841 goto err_free_netdev;
5842
5843 status = hdd_register_hostapd( pAdapter, rtnl_held );
5844 if( VOS_STATUS_SUCCESS != status )
5845 {
5846 hdd_deinit_adapter(pHddCtx, pAdapter);
5847 goto err_free_netdev;
5848 }
5849
5850 netif_tx_disable(pAdapter->dev);
5851 netif_carrier_off(pAdapter->dev);
5852
5853 hdd_set_conparam( 1 );
5854 break;
5855 }
5856 case WLAN_HDD_MONITOR:
5857 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005858 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5859 if( NULL == pAdapter )
5860 return NULL;
5861
5862 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5863 pAdapter->device_mode = session_type;
5864 status = hdd_register_interface( pAdapter, rtnl_held );
5865#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5866 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5867#else
5868 pAdapter->dev->open = hdd_mon_open;
5869 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5870#endif
5871 hdd_init_tx_rx( pAdapter );
5872 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5873 //Set adapter to be used for data tx. It will use either GO or softap.
5874 pAdapter->sessionCtx.monitor.pAdapterForTx =
5875 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005876 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5877 {
5878 pAdapter->sessionCtx.monitor.pAdapterForTx =
5879 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5880 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005881 /* This workqueue will be used to transmit management packet over
5882 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005883 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5884 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5885 return NULL;
5886 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005887
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5889 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005890 }
5891 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005892 case WLAN_HDD_FTM:
5893 {
5894 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5895
5896 if( NULL == pAdapter )
5897 return NULL;
5898 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5899 * message while loading driver in FTM mode. */
5900 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5901 pAdapter->device_mode = session_type;
5902 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305903
5904 hdd_init_tx_rx( pAdapter );
5905
5906 //Stop the Interface TX queue.
5907 netif_tx_disable(pAdapter->dev);
5908 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005909 }
5910 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005911 default:
5912 {
5913 VOS_ASSERT(0);
5914 return NULL;
5915 }
5916 }
5917
Jeff Johnson295189b2012-06-20 16:38:30 -07005918 if( VOS_STATUS_SUCCESS == status )
5919 {
5920 //Add it to the hdd's session list.
5921 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5922 if( NULL == pHddAdapterNode )
5923 {
5924 status = VOS_STATUS_E_NOMEM;
5925 }
5926 else
5927 {
5928 pHddAdapterNode->pAdapter = pAdapter;
5929 status = hdd_add_adapter_back ( pHddCtx,
5930 pHddAdapterNode );
5931 }
5932 }
5933
5934 if( VOS_STATUS_SUCCESS != status )
5935 {
5936 if( NULL != pAdapter )
5937 {
5938 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5939 pAdapter = NULL;
5940 }
5941 if( NULL != pHddAdapterNode )
5942 {
5943 vos_mem_free( pHddAdapterNode );
5944 }
5945
5946 goto resume_bmps;
5947 }
5948
5949 if(VOS_STATUS_SUCCESS == status)
5950 {
5951 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5952
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005953 //Initialize the WoWL service
5954 if(!hdd_init_wowl(pAdapter))
5955 {
5956 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5957 goto err_free_netdev;
5958 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005959 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005960 return pAdapter;
5961
5962err_free_netdev:
5963 free_netdev(pAdapter->dev);
5964 wlan_hdd_release_intf_addr( pHddCtx,
5965 pAdapter->macAddressCurrent.bytes );
5966
5967resume_bmps:
5968 //If bmps disabled enable it
5969 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5970 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305971 if (pHddCtx->hdd_wlan_suspended)
5972 {
5973 hdd_set_pwrparams(pHddCtx);
5974 }
5975 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005976 }
5977 return NULL;
5978}
5979
5980VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5981 tANI_U8 rtnl_held )
5982{
5983 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5984 VOS_STATUS status;
5985
5986 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5987 if( VOS_STATUS_SUCCESS != status )
5988 return status;
5989
5990 while ( pCurrent->pAdapter != pAdapter )
5991 {
5992 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5993 if( VOS_STATUS_SUCCESS != status )
5994 break;
5995
5996 pCurrent = pNext;
5997 }
5998 pAdapterNode = pCurrent;
5999 if( VOS_STATUS_SUCCESS == status )
6000 {
6001 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6002 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306003
6004#ifdef FEATURE_WLAN_TDLS
6005
6006 /* A Mutex Lock is introduced while changing/initializing the mode to
6007 * protect the concurrent access for the Adapters by TDLS module.
6008 */
6009 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6010 {
6011 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6012 "%s: unable to lock list", __func__);
6013 return VOS_STATUS_E_FAILURE;
6014 }
6015#endif
6016
Jeff Johnson295189b2012-06-20 16:38:30 -07006017 hdd_remove_adapter( pHddCtx, pAdapterNode );
6018 vos_mem_free( pAdapterNode );
6019
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306020#ifdef FEATURE_WLAN_TDLS
6021 mutex_unlock(&pHddCtx->tdls_lock);
6022#endif
6023
Jeff Johnson295189b2012-06-20 16:38:30 -07006024
6025 /* If there is a single session of STA/P2P client, re-enable BMPS */
6026 if ((!vos_concurrent_sessions_running()) &&
6027 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6028 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6029 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306030 if (pHddCtx->hdd_wlan_suspended)
6031 {
6032 hdd_set_pwrparams(pHddCtx);
6033 }
6034 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006035 }
6036
6037 return VOS_STATUS_SUCCESS;
6038 }
6039
6040 return VOS_STATUS_E_FAILURE;
6041}
6042
6043VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6044{
6045 hdd_adapter_list_node_t *pHddAdapterNode;
6046 VOS_STATUS status;
6047
6048 ENTER();
6049
6050 do
6051 {
6052 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6053 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6054 {
6055 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6056 vos_mem_free( pHddAdapterNode );
6057 }
6058 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6059
6060 EXIT();
6061
6062 return VOS_STATUS_SUCCESS;
6063}
6064
6065void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6066{
6067 v_U8_t addIE[1] = {0};
6068
6069 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6070 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6071 eANI_BOOLEAN_FALSE) )
6072 {
6073 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006074 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006075 }
6076
6077 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6078 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6079 eANI_BOOLEAN_FALSE) )
6080 {
6081 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006082 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006083 }
6084
6085 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6086 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6087 eANI_BOOLEAN_FALSE) )
6088 {
6089 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006090 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006091 }
6092}
6093
6094VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6095{
6096 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6097 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6098 union iwreq_data wrqu;
6099
6100 ENTER();
6101
6102 switch(pAdapter->device_mode)
6103 {
6104 case WLAN_HDD_INFRA_STATION:
6105 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006106 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006107 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6108 {
6109 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6110 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6111 pAdapter->sessionId,
6112 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6113 else
6114 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6115 pAdapter->sessionId,
6116 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6117 //success implies disconnect command got queued up successfully
6118 if(halStatus == eHAL_STATUS_SUCCESS)
6119 {
6120 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6121 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6122 }
6123 memset(&wrqu, '\0', sizeof(wrqu));
6124 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6125 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6126 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6127 }
6128 else
6129 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306130 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006131 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306132#ifdef WLAN_OPEN_SOURCE
6133#ifdef WLAN_NS_OFFLOAD
6134 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6135#endif
6136#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006137
6138 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6139 {
6140 INIT_COMPLETION(pAdapter->session_close_comp_var);
6141 if (eHAL_STATUS_SUCCESS ==
6142 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6143 hdd_smeCloseSessionCallback, pAdapter))
6144 {
6145 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006146 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006147 &pAdapter->session_close_comp_var,
6148 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6149 }
6150 }
6151
6152 break;
6153
6154 case WLAN_HDD_SOFTAP:
6155 case WLAN_HDD_P2P_GO:
6156 //Any softap specific cleanup here...
6157 mutex_lock(&pHddCtx->sap_lock);
6158 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6159 {
6160 VOS_STATUS status;
6161 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6162
6163 //Stop Bss.
6164 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6165 if (VOS_IS_STATUS_SUCCESS(status))
6166 {
6167 hdd_hostapd_state_t *pHostapdState =
6168 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6169
6170 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6171
6172 if (!VOS_IS_STATUS_SUCCESS(status))
6173 {
6174 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006175 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006176 }
6177 }
6178 else
6179 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006180 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 }
6182 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6183
6184 if (eHAL_STATUS_FAILURE ==
6185 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6186 0, NULL, eANI_BOOLEAN_FALSE))
6187 {
6188 hddLog(LOGE,
6189 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006190 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006191 }
6192
6193 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6194 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6195 eANI_BOOLEAN_FALSE) )
6196 {
6197 hddLog(LOGE,
6198 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6199 }
6200
6201 // Reset WNI_CFG_PROBE_RSP Flags
6202 wlan_hdd_reset_prob_rspies(pAdapter);
6203 kfree(pAdapter->sessionCtx.ap.beacon);
6204 pAdapter->sessionCtx.ap.beacon = NULL;
6205 }
6206 mutex_unlock(&pHddCtx->sap_lock);
6207 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006208
Jeff Johnson295189b2012-06-20 16:38:30 -07006209 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006210#ifdef WLAN_OPEN_SOURCE
6211 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6212#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006213 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006214
Jeff Johnson295189b2012-06-20 16:38:30 -07006215 default:
6216 break;
6217 }
6218
6219 EXIT();
6220 return VOS_STATUS_SUCCESS;
6221}
6222
6223VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6224{
6225 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6226 VOS_STATUS status;
6227 hdd_adapter_t *pAdapter;
6228
6229 ENTER();
6230
6231 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6232
6233 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6234 {
6235 pAdapter = pAdapterNode->pAdapter;
6236 netif_tx_disable(pAdapter->dev);
6237 netif_carrier_off(pAdapter->dev);
6238
6239 hdd_stop_adapter( pHddCtx, pAdapter );
6240
6241 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6242 pAdapterNode = pNext;
6243 }
6244
6245 EXIT();
6246
6247 return VOS_STATUS_SUCCESS;
6248}
6249
6250VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6251{
6252 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6253 VOS_STATUS status;
6254 hdd_adapter_t *pAdapter;
6255
6256 ENTER();
6257
6258 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6259
6260 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6261 {
6262 pAdapter = pAdapterNode->pAdapter;
6263 netif_tx_disable(pAdapter->dev);
6264 netif_carrier_off(pAdapter->dev);
6265
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006266 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6267
Jeff Johnson295189b2012-06-20 16:38:30 -07006268 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306269 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6270 {
6271 hdd_wmm_adapter_close( pAdapter );
6272 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6273 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006274
6275 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6276 pAdapterNode = pNext;
6277 }
6278
6279 EXIT();
6280
6281 return VOS_STATUS_SUCCESS;
6282}
6283
6284VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6285{
6286 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6287 VOS_STATUS status;
6288 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306289 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006290
6291 ENTER();
6292
6293 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6294
6295 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6296 {
6297 pAdapter = pAdapterNode->pAdapter;
6298
6299 switch(pAdapter->device_mode)
6300 {
6301 case WLAN_HDD_INFRA_STATION:
6302 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006303 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306304
6305 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6306
Jeff Johnson295189b2012-06-20 16:38:30 -07006307 hdd_init_station_mode(pAdapter);
6308 /* Open the gates for HDD to receive Wext commands */
6309 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006310 pHddCtx->scan_info.mScanPending = FALSE;
6311 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006312
6313 //Trigger the initial scan
6314 hdd_wlan_initial_scan(pAdapter);
6315
6316 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306317 if (eConnectionState_Associated == connState ||
6318 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006319 {
6320 union iwreq_data wrqu;
6321 memset(&wrqu, '\0', sizeof(wrqu));
6322 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6323 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6324 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006325 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006326
Jeff Johnson295189b2012-06-20 16:38:30 -07006327 /* indicate disconnected event to nl80211 */
6328 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6329 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006330 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306331 else if (eConnectionState_Connecting == connState)
6332 {
6333 /*
6334 * Indicate connect failure to supplicant if we were in the
6335 * process of connecting
6336 */
6337 cfg80211_connect_result(pAdapter->dev, NULL,
6338 NULL, 0, NULL, 0,
6339 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6340 GFP_KERNEL);
6341 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006342 break;
6343
6344 case WLAN_HDD_SOFTAP:
6345 /* softAP can handle SSR */
6346 break;
6347
6348 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006349 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006350 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006351 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006352 break;
6353
6354 case WLAN_HDD_MONITOR:
6355 /* monitor interface start */
6356 break;
6357 default:
6358 break;
6359 }
6360
6361 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6362 pAdapterNode = pNext;
6363 }
6364
6365 EXIT();
6366
6367 return VOS_STATUS_SUCCESS;
6368}
6369
6370VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6371{
6372 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6373 hdd_adapter_t *pAdapter;
6374 VOS_STATUS status;
6375 v_U32_t roamId;
6376
6377 ENTER();
6378
6379 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6380
6381 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6382 {
6383 pAdapter = pAdapterNode->pAdapter;
6384
6385 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6386 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6387 {
6388 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6389 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6390
6391 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6392 init_completion(&pAdapter->disconnect_comp_var);
6393 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6394 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6395
6396 wait_for_completion_interruptible_timeout(
6397 &pAdapter->disconnect_comp_var,
6398 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6399
6400 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6401 pHddCtx->isAmpAllowed = VOS_FALSE;
6402 sme_RoamConnect(pHddCtx->hHal,
6403 pAdapter->sessionId, &(pWextState->roamProfile),
6404 &roamId);
6405 }
6406
6407 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6408 pAdapterNode = pNext;
6409 }
6410
6411 EXIT();
6412
6413 return VOS_STATUS_SUCCESS;
6414}
6415
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006416void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6417{
6418 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6419 VOS_STATUS status;
6420 hdd_adapter_t *pAdapter;
6421 hdd_station_ctx_t *pHddStaCtx;
6422 hdd_ap_ctx_t *pHddApCtx;
6423 hdd_hostapd_state_t * pHostapdState;
6424 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6425 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6426 const char *p2pMode = "DEV";
6427 const char *ccMode = "Standalone";
6428 int n;
6429
6430 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6431 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6432 {
6433 pAdapter = pAdapterNode->pAdapter;
6434 switch (pAdapter->device_mode) {
6435 case WLAN_HDD_INFRA_STATION:
6436 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6437 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6438 staChannel = pHddStaCtx->conn_info.operationChannel;
6439 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6440 }
6441 break;
6442 case WLAN_HDD_P2P_CLIENT:
6443 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6444 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6445 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6446 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6447 p2pMode = "CLI";
6448 }
6449 break;
6450 case WLAN_HDD_P2P_GO:
6451 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6452 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6453 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6454 p2pChannel = pHddApCtx->operatingChannel;
6455 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6456 }
6457 p2pMode = "GO";
6458 break;
6459 case WLAN_HDD_SOFTAP:
6460 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6461 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6462 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6463 apChannel = pHddApCtx->operatingChannel;
6464 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6465 }
6466 break;
6467 default:
6468 break;
6469 }
6470 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6471 pAdapterNode = pNext;
6472 }
6473 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6474 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6475 }
6476 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6477 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6478 if (p2pChannel > 0) {
6479 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6480 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6481 }
6482 if (apChannel > 0) {
6483 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6484 apChannel, MAC_ADDR_ARRAY(apBssid));
6485 }
6486
6487 if (p2pChannel > 0 && apChannel > 0) {
6488 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6489 }
6490}
6491
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006492bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006493{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006494 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006495}
6496
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006497/* Once SSR is disabled then it cannot be set. */
6498void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006499{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006500 if (HDD_SSR_DISABLED == isSsrRequired)
6501 return;
6502
Jeff Johnson295189b2012-06-20 16:38:30 -07006503 isSsrRequired = value;
6504}
6505
6506VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6507 hdd_adapter_list_node_t** ppAdapterNode)
6508{
6509 VOS_STATUS status;
6510 spin_lock(&pHddCtx->hddAdapters.lock);
6511 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6512 (hdd_list_node_t**) ppAdapterNode );
6513 spin_unlock(&pHddCtx->hddAdapters.lock);
6514 return status;
6515}
6516
6517VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6518 hdd_adapter_list_node_t* pAdapterNode,
6519 hdd_adapter_list_node_t** pNextAdapterNode)
6520{
6521 VOS_STATUS status;
6522 spin_lock(&pHddCtx->hddAdapters.lock);
6523 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6524 (hdd_list_node_t*) pAdapterNode,
6525 (hdd_list_node_t**)pNextAdapterNode );
6526
6527 spin_unlock(&pHddCtx->hddAdapters.lock);
6528 return status;
6529}
6530
6531VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6532 hdd_adapter_list_node_t* pAdapterNode)
6533{
6534 VOS_STATUS status;
6535 spin_lock(&pHddCtx->hddAdapters.lock);
6536 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6537 &pAdapterNode->node );
6538 spin_unlock(&pHddCtx->hddAdapters.lock);
6539 return status;
6540}
6541
6542VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6543 hdd_adapter_list_node_t** ppAdapterNode)
6544{
6545 VOS_STATUS status;
6546 spin_lock(&pHddCtx->hddAdapters.lock);
6547 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6548 (hdd_list_node_t**) ppAdapterNode );
6549 spin_unlock(&pHddCtx->hddAdapters.lock);
6550 return status;
6551}
6552
6553VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6554 hdd_adapter_list_node_t* pAdapterNode)
6555{
6556 VOS_STATUS status;
6557 spin_lock(&pHddCtx->hddAdapters.lock);
6558 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6559 (hdd_list_node_t*) pAdapterNode );
6560 spin_unlock(&pHddCtx->hddAdapters.lock);
6561 return status;
6562}
6563
6564VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6565 hdd_adapter_list_node_t* pAdapterNode)
6566{
6567 VOS_STATUS status;
6568 spin_lock(&pHddCtx->hddAdapters.lock);
6569 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6570 (hdd_list_node_t*) pAdapterNode );
6571 spin_unlock(&pHddCtx->hddAdapters.lock);
6572 return status;
6573}
6574
6575hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6576 tSirMacAddr macAddr )
6577{
6578 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6579 hdd_adapter_t *pAdapter;
6580 VOS_STATUS status;
6581
6582 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6583
6584 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6585 {
6586 pAdapter = pAdapterNode->pAdapter;
6587
6588 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6589 macAddr, sizeof(tSirMacAddr) ) )
6590 {
6591 return pAdapter;
6592 }
6593 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6594 pAdapterNode = pNext;
6595 }
6596
6597 return NULL;
6598
6599}
6600
6601hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6602{
6603 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6604 hdd_adapter_t *pAdapter;
6605 VOS_STATUS status;
6606
6607 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6608
6609 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6610 {
6611 pAdapter = pAdapterNode->pAdapter;
6612
6613 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6614 IFNAMSIZ ) )
6615 {
6616 return pAdapter;
6617 }
6618 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6619 pAdapterNode = pNext;
6620 }
6621
6622 return NULL;
6623
6624}
6625
6626hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6627{
6628 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6629 hdd_adapter_t *pAdapter;
6630 VOS_STATUS status;
6631
6632 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6633
6634 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6635 {
6636 pAdapter = pAdapterNode->pAdapter;
6637
6638 if( pAdapter && (mode == pAdapter->device_mode) )
6639 {
6640 return pAdapter;
6641 }
6642 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6643 pAdapterNode = pNext;
6644 }
6645
6646 return NULL;
6647
6648}
6649
6650//Remove this function later
6651hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6652{
6653 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6654 hdd_adapter_t *pAdapter;
6655 VOS_STATUS status;
6656
6657 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6658
6659 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6660 {
6661 pAdapter = pAdapterNode->pAdapter;
6662
6663 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6664 {
6665 return pAdapter;
6666 }
6667
6668 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6669 pAdapterNode = pNext;
6670 }
6671
6672 return NULL;
6673
6674}
6675
Jeff Johnson295189b2012-06-20 16:38:30 -07006676/**---------------------------------------------------------------------------
6677
6678 \brief hdd_set_monitor_tx_adapter() -
6679
6680 This API initializes the adapter to be used while transmitting on monitor
6681 adapter.
6682
6683 \param - pHddCtx - Pointer to the HDD context.
6684 pAdapter - Adapter that will used for TX. This can be NULL.
6685 \return - None.
6686 --------------------------------------------------------------------------*/
6687void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6688{
6689 hdd_adapter_t *pMonAdapter;
6690
6691 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6692
6693 if( NULL != pMonAdapter )
6694 {
6695 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6696 }
6697}
Jeff Johnson295189b2012-06-20 16:38:30 -07006698/**---------------------------------------------------------------------------
6699
6700 \brief hdd_select_queue() -
6701
6702 This API returns the operating channel of the requested device mode
6703
6704 \param - pHddCtx - Pointer to the HDD context.
6705 - mode - Device mode for which operating channel is required
6706 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6707 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6708 \return - channel number. "0" id the requested device is not found OR it is not connected.
6709 --------------------------------------------------------------------------*/
6710v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6711{
6712 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6713 VOS_STATUS status;
6714 hdd_adapter_t *pAdapter;
6715 v_U8_t operatingChannel = 0;
6716
6717 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6718
6719 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6720 {
6721 pAdapter = pAdapterNode->pAdapter;
6722
6723 if( mode == pAdapter->device_mode )
6724 {
6725 switch(pAdapter->device_mode)
6726 {
6727 case WLAN_HDD_INFRA_STATION:
6728 case WLAN_HDD_P2P_CLIENT:
6729 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6730 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6731 break;
6732 case WLAN_HDD_SOFTAP:
6733 case WLAN_HDD_P2P_GO:
6734 /*softap connection info */
6735 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6736 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6737 break;
6738 default:
6739 break;
6740 }
6741
6742 break; //Found the device of interest. break the loop
6743 }
6744
6745 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6746 pAdapterNode = pNext;
6747 }
6748 return operatingChannel;
6749}
6750
6751#ifdef WLAN_FEATURE_PACKET_FILTERING
6752/**---------------------------------------------------------------------------
6753
6754 \brief hdd_set_multicast_list() -
6755
6756 This used to set the multicast address list.
6757
6758 \param - dev - Pointer to the WLAN device.
6759 - skb - Pointer to OS packet (sk_buff).
6760 \return - success/fail
6761
6762 --------------------------------------------------------------------------*/
6763static void hdd_set_multicast_list(struct net_device *dev)
6764{
6765 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006766 int mc_count;
6767 int i = 0;
6768 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306769
6770 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006771 {
6772 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306773 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006774 return;
6775 }
6776
6777 if (dev->flags & IFF_ALLMULTI)
6778 {
6779 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006780 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306781 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006782 }
6783 else
6784 {
6785 mc_count = netdev_mc_count(dev);
6786 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006787 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006788 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6789 {
6790 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006791 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306792 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006793 return;
6794 }
6795
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306796 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006797
6798 netdev_for_each_mc_addr(ha, dev) {
6799 if (i == mc_count)
6800 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306801 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6802 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08006803 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006804 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306805 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006806 i++;
6807 }
6808 }
6809 return;
6810}
6811#endif
6812
6813/**---------------------------------------------------------------------------
6814
6815 \brief hdd_select_queue() -
6816
6817 This function is registered with the Linux OS for network
6818 core to decide which queue to use first.
6819
6820 \param - dev - Pointer to the WLAN device.
6821 - skb - Pointer to OS packet (sk_buff).
6822 \return - ac, Queue Index/access category corresponding to UP in IP header
6823
6824 --------------------------------------------------------------------------*/
6825v_U16_t hdd_select_queue(struct net_device *dev,
6826 struct sk_buff *skb)
6827{
6828 return hdd_wmm_select_queue(dev, skb);
6829}
6830
6831
6832/**---------------------------------------------------------------------------
6833
6834 \brief hdd_wlan_initial_scan() -
6835
6836 This function triggers the initial scan
6837
6838 \param - pAdapter - Pointer to the HDD adapter.
6839
6840 --------------------------------------------------------------------------*/
6841void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6842{
6843 tCsrScanRequest scanReq;
6844 tCsrChannelInfo channelInfo;
6845 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006846 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006847 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6848
6849 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6850 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6851 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6852
6853 if(sme_Is11dSupported(pHddCtx->hHal))
6854 {
6855 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6856 if ( HAL_STATUS_SUCCESS( halStatus ) )
6857 {
6858 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6859 if( !scanReq.ChannelInfo.ChannelList )
6860 {
6861 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6862 vos_mem_free(channelInfo.ChannelList);
6863 return;
6864 }
6865 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6866 channelInfo.numOfChannels);
6867 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6868 vos_mem_free(channelInfo.ChannelList);
6869 }
6870
6871 scanReq.scanType = eSIR_PASSIVE_SCAN;
6872 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6873 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6874 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6875 }
6876 else
6877 {
6878 scanReq.scanType = eSIR_ACTIVE_SCAN;
6879 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6880 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6881 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6882 }
6883
6884 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6885 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6886 {
6887 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6888 __func__, halStatus );
6889 }
6890
6891 if(sme_Is11dSupported(pHddCtx->hHal))
6892 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6893}
6894
6895struct fullPowerContext
6896{
6897 struct completion completion;
6898 unsigned int magic;
6899};
6900#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6901
6902/**---------------------------------------------------------------------------
6903
6904 \brief hdd_full_power_callback() - HDD full power callback function
6905
6906 This is the function invoked by SME to inform the result of a full power
6907 request issued by HDD
6908
6909 \param - callbackcontext - Pointer to cookie
6910 \param - status - result of request
6911
6912 \return - None
6913
6914 --------------------------------------------------------------------------*/
6915static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6916{
6917 struct fullPowerContext *pContext = callbackContext;
6918
6919 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306920 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006921
6922 if (NULL == callbackContext)
6923 {
6924 hddLog(VOS_TRACE_LEVEL_ERROR,
6925 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006926 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006927 return;
6928 }
6929
6930 /* there is a race condition that exists between this callback function
6931 and the caller since the caller could time out either before or
6932 while this code is executing. we'll assume the timeout hasn't
6933 occurred, but we'll verify that right before we save our work */
6934
6935 if (POWER_CONTEXT_MAGIC != pContext->magic)
6936 {
6937 /* the caller presumably timed out so there is nothing we can do */
6938 hddLog(VOS_TRACE_LEVEL_WARN,
6939 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006940 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006941 return;
6942 }
6943
6944 /* the race is on. caller could have timed out immediately after
6945 we verified the magic, but if so, caller will wait a short time
6946 for us to notify the caller, so the context will stay valid */
6947 complete(&pContext->completion);
6948}
6949
6950/**---------------------------------------------------------------------------
6951
6952 \brief hdd_wlan_exit() - HDD WLAN exit function
6953
6954 This is the driver exit point (invoked during rmmod)
6955
6956 \param - pHddCtx - Pointer to the HDD Context
6957
6958 \return - None
6959
6960 --------------------------------------------------------------------------*/
6961void hdd_wlan_exit(hdd_context_t *pHddCtx)
6962{
6963 eHalStatus halStatus;
6964 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6965 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306966 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006967 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006968 struct fullPowerContext powerContext;
6969 long lrc;
6970
6971 ENTER();
6972
Jeff Johnson88ba7742013-02-27 14:36:02 -08006973 if (VOS_FTM_MODE != hdd_get_conparam())
6974 {
6975 // Unloading, restart logic is no more required.
6976 wlan_hdd_restart_deinit(pHddCtx);
6977 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006978
Jeff Johnson295189b2012-06-20 16:38:30 -07006979 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006980 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006981 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006982 {
6983 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6984 WLAN_HDD_INFRA_STATION);
6985 if (pAdapter == NULL)
6986 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6987
6988 if (pAdapter != NULL)
6989 {
6990 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6991 hdd_UnregisterWext(pAdapter->dev);
6992 }
6993 }
6994 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006995
Jeff Johnson295189b2012-06-20 16:38:30 -07006996 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006997 {
6998 wlan_hdd_ftm_close(pHddCtx);
6999 goto free_hdd_ctx;
7000 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007001 //Stop the Interface TX queue.
7002 //netif_tx_disable(pWlanDev);
7003 //netif_carrier_off(pWlanDev);
7004
Jeff Johnson295189b2012-06-20 16:38:30 -07007005 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7006 {
7007 pAdapter = hdd_get_adapter(pHddCtx,
7008 WLAN_HDD_SOFTAP);
7009 }
7010 else
7011 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007012 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007013 {
7014 pAdapter = hdd_get_adapter(pHddCtx,
7015 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007016 if (pAdapter == NULL)
7017 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007018 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007019 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007020 /* DeRegister with platform driver as client for Suspend/Resume */
7021 vosStatus = hddDeregisterPmOps(pHddCtx);
7022 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7023 {
7024 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7025 VOS_ASSERT(0);
7026 }
7027
7028 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7029 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7030 {
7031 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7032 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007033
7034 // Cancel any outstanding scan requests. We are about to close all
7035 // of our adapters, but an adapter structure is what SME passes back
7036 // to our callback function. Hence if there are any outstanding scan
7037 // requests then there is a race condition between when the adapter
7038 // is closed and when the callback is invoked. We try to resolve that
7039 // race condition here by canceling any outstanding scans before we
7040 // close the adapters.
7041 // Note that the scans may be cancelled in an asynchronous manner, so
7042 // ideally there needs to be some kind of synchronization. Rather than
7043 // introduce a new synchronization here, we will utilize the fact that
7044 // we are about to Request Full Power, and since that is synchronized,
7045 // the expectation is that by the time Request Full Power has completed,
7046 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007047 if (NULL != pAdapter)
7048 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7049 else
7050 hddLog(VOS_TRACE_LEVEL_ERROR,
7051 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007052
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007053 //Stop the traffic monitor timer
7054 if ( VOS_TIMER_STATE_RUNNING ==
7055 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7056 {
7057 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7058 }
7059
7060 // Destroy the traffic monitor timer
7061 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7062 &pHddCtx->tx_rx_trafficTmr)))
7063 {
7064 hddLog(VOS_TRACE_LEVEL_ERROR,
7065 "%s: Cannot deallocate Traffic monitor timer", __func__);
7066 }
7067
Jeff Johnson295189b2012-06-20 16:38:30 -07007068 //Disable IMPS/BMPS as we do not want the device to enter any power
7069 //save mode during shutdown
7070 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7071 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7072 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7073
7074 //Ensure that device is in full power as we will touch H/W during vos_Stop
7075 init_completion(&powerContext.completion);
7076 powerContext.magic = POWER_CONTEXT_MAGIC;
7077
7078 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7079 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7080
7081 if (eHAL_STATUS_SUCCESS != halStatus)
7082 {
7083 if (eHAL_STATUS_PMC_PENDING == halStatus)
7084 {
7085 /* request was sent -- wait for the response */
7086 lrc = wait_for_completion_interruptible_timeout(
7087 &powerContext.completion,
7088 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
7089 /* either we have a response or we timed out
7090 either way, first invalidate our magic */
7091 powerContext.magic = 0;
7092 if (lrc <= 0)
7093 {
7094 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007095 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007096 /* there is a race condition such that the callback
7097 function could be executing at the same time we are. of
7098 primary concern is if the callback function had already
7099 verified the "magic" but hasn't yet set the completion
7100 variable. Since the completion variable is on our
7101 stack, we'll delay just a bit to make sure the data is
7102 still valid if that is the case */
7103 msleep(50);
7104 }
7105 }
7106 else
7107 {
7108 hddLog(VOS_TRACE_LEVEL_ERROR,
7109 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007110 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007111 VOS_ASSERT(0);
7112 /* continue -- need to clean up as much as possible */
7113 }
7114 }
7115
Yue Ma0d4891e2013-08-06 17:01:45 -07007116 hdd_debugfs_exit(pHddCtx);
7117
Jeff Johnson295189b2012-06-20 16:38:30 -07007118 // Unregister the Net Device Notifier
7119 unregister_netdevice_notifier(&hdd_netdev_notifier);
7120
Jeff Johnson295189b2012-06-20 16:38:30 -07007121 hdd_stop_all_adapters( pHddCtx );
7122
Jeff Johnson295189b2012-06-20 16:38:30 -07007123#ifdef WLAN_BTAMP_FEATURE
7124 vosStatus = WLANBAP_Stop(pVosContext);
7125 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7126 {
7127 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7128 "%s: Failed to stop BAP",__func__);
7129 }
7130#endif //WLAN_BTAMP_FEATURE
7131
7132 //Stop all the modules
7133 vosStatus = vos_stop( pVosContext );
7134 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7135 {
7136 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7137 "%s: Failed to stop VOSS",__func__);
7138 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7139 }
7140
Jeff Johnson295189b2012-06-20 16:38:30 -07007141 //Assert Deep sleep signal now to put Libra HW in lowest power state
7142 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7143 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7144
7145 //Vote off any PMIC voltage supplies
7146 vos_chipPowerDown(NULL, NULL, NULL);
7147
7148 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7149
Leo Chang59cdc7e2013-07-10 10:08:21 -07007150
Jeff Johnson295189b2012-06-20 16:38:30 -07007151 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007152 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007153
7154 //Close the scheduler before calling vos_close to make sure no thread is
7155 // scheduled after the each module close is called i.e after all the data
7156 // structures are freed.
7157 vosStatus = vos_sched_close( pVosContext );
7158 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7159 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7160 "%s: Failed to close VOSS Scheduler",__func__);
7161 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7162 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007163#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007164#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7165 /* Destroy the wake lock */
7166 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7167#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007168 /* Destroy the wake lock */
7169 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007170#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007171
7172 //Close VOSS
7173 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7174 vos_close(pVosContext);
7175
Jeff Johnson295189b2012-06-20 16:38:30 -07007176 //Close Watchdog
7177 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7178 vos_watchdog_close(pVosContext);
7179
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307180 //Clean up HDD Nlink Service
7181 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007182#ifdef WLAN_KD_READY_NOTIFIER
7183 nl_srv_exit(pHddCtx->ptt_pid);
7184#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307185 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007186#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307187
Jeff Johnson295189b2012-06-20 16:38:30 -07007188 /* Cancel the vote for XO Core ON.
7189 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7190 * exited at this point
7191 */
7192 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007193 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007194 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7195 {
7196 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7197 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007198 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007199 }
7200
7201 hdd_close_all_adapters( pHddCtx );
7202
7203
7204 //Free up dynamically allocated members inside HDD Adapter
7205 kfree(pHddCtx->cfg_ini);
7206 pHddCtx->cfg_ini= NULL;
7207
7208 /* free the power on lock from platform driver */
7209 if (free_riva_power_on_lock("wlan"))
7210 {
7211 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7212 __func__);
7213 }
7214
Jeff Johnson88ba7742013-02-27 14:36:02 -08007215free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007216 /* FTM mode, WIPHY did not registered
7217 If un-register here, system crash will happen */
7218 if (VOS_FTM_MODE != hdd_get_conparam())
7219 {
7220 wiphy_unregister(wiphy) ;
7221 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007222 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007223 if (hdd_is_ssr_required())
7224 {
7225 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007226 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007227 msleep(5000);
7228 }
7229 hdd_set_ssr_required (VOS_FALSE);
7230}
7231
7232
7233/**---------------------------------------------------------------------------
7234
7235 \brief hdd_update_config_from_nv() - Function to update the contents of
7236 the running configuration with parameters taken from NV storage
7237
7238 \param - pHddCtx - Pointer to the HDD global context
7239
7240 \return - VOS_STATUS_SUCCESS if successful
7241
7242 --------------------------------------------------------------------------*/
7243static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7244{
Jeff Johnson295189b2012-06-20 16:38:30 -07007245 v_BOOL_t itemIsValid = VOS_FALSE;
7246 VOS_STATUS status;
7247 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7248 v_U8_t macLoop;
7249
7250 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7251 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7252 if(status != VOS_STATUS_SUCCESS)
7253 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007254 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007255 return VOS_STATUS_E_FAILURE;
7256 }
7257
7258 if (itemIsValid == VOS_TRUE)
7259 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007260 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007261 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7262 VOS_MAX_CONCURRENCY_PERSONA);
7263 if(status != VOS_STATUS_SUCCESS)
7264 {
7265 /* Get MAC from NV fail, not update CFG info
7266 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007267 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007268 return VOS_STATUS_E_FAILURE;
7269 }
7270
7271 /* If first MAC is not valid, treat all others are not valid
7272 * Then all MACs will be got from ini file */
7273 if(vos_is_macaddr_zero(&macFromNV[0]))
7274 {
7275 /* MAC address in NV file is not configured yet */
7276 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7277 return VOS_STATUS_E_INVAL;
7278 }
7279
7280 /* Get MAC address from NV, update CFG info */
7281 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7282 {
7283 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7284 {
7285 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7286 /* This MAC is not valid, skip it
7287 * This MAC will be got from ini file */
7288 }
7289 else
7290 {
7291 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7292 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7293 VOS_MAC_ADDR_SIZE);
7294 }
7295 }
7296 }
7297 else
7298 {
7299 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7300 return VOS_STATUS_E_FAILURE;
7301 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007302
Jeff Johnson295189b2012-06-20 16:38:30 -07007303
7304 return VOS_STATUS_SUCCESS;
7305}
7306
7307/**---------------------------------------------------------------------------
7308
7309 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7310
7311 \param - pAdapter - Pointer to the HDD
7312
7313 \return - None
7314
7315 --------------------------------------------------------------------------*/
7316VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7317{
7318 eHalStatus halStatus;
7319 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307320 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007321
Jeff Johnson295189b2012-06-20 16:38:30 -07007322
7323 // Send ready indication to the HDD. This will kick off the MAC
7324 // into a 'running' state and should kick off an initial scan.
7325 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7326 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7327 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307328 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007329 "code %08d [x%08x]",__func__, halStatus, halStatus );
7330 return VOS_STATUS_E_FAILURE;
7331 }
7332
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307333 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007334 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7335 // And RIVA will crash
7336 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7337 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307338 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7339 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7340
7341
Jeff Johnson295189b2012-06-20 16:38:30 -07007342 return VOS_STATUS_SUCCESS;
7343}
7344
Jeff Johnson295189b2012-06-20 16:38:30 -07007345/* wake lock APIs for HDD */
7346void hdd_prevent_suspend(void)
7347{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007348#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007349 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007350#else
7351 wcnss_prevent_suspend();
7352#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007353}
7354
7355void hdd_allow_suspend(void)
7356{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007357#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007358 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007359#else
7360 wcnss_allow_suspend();
7361#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007362}
7363
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007364void hdd_allow_suspend_timeout(v_U32_t timeout)
7365{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007366#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007367 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007368#else
7369 /* Do nothing as there is no API in wcnss for timeout*/
7370#endif
7371}
7372
Jeff Johnson295189b2012-06-20 16:38:30 -07007373/**---------------------------------------------------------------------------
7374
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007375 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7376 information between Host and Riva
7377
7378 This function gets reported version of FW
7379 It also finds the version of Riva headers used to compile the host
7380 It compares the above two and prints a warning if they are different
7381 It gets the SW and HW version string
7382 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7383 indicating the features they support through a bitmap
7384
7385 \param - pHddCtx - Pointer to HDD context
7386
7387 \return - void
7388
7389 --------------------------------------------------------------------------*/
7390
7391void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7392{
7393
7394 tSirVersionType versionCompiled;
7395 tSirVersionType versionReported;
7396 tSirVersionString versionString;
7397 tANI_U8 fwFeatCapsMsgSupported = 0;
7398 VOS_STATUS vstatus;
7399
7400 /* retrieve and display WCNSS version information */
7401 do {
7402
7403 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7404 &versionCompiled);
7405 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7406 {
7407 hddLog(VOS_TRACE_LEVEL_FATAL,
7408 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007409 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007410 break;
7411 }
7412
7413 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7414 &versionReported);
7415 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7416 {
7417 hddLog(VOS_TRACE_LEVEL_FATAL,
7418 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007419 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007420 break;
7421 }
7422
7423 if ((versionCompiled.major != versionReported.major) ||
7424 (versionCompiled.minor != versionReported.minor) ||
7425 (versionCompiled.version != versionReported.version) ||
7426 (versionCompiled.revision != versionReported.revision))
7427 {
7428 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7429 "Host expected %u.%u.%u.%u\n",
7430 WLAN_MODULE_NAME,
7431 (int)versionReported.major,
7432 (int)versionReported.minor,
7433 (int)versionReported.version,
7434 (int)versionReported.revision,
7435 (int)versionCompiled.major,
7436 (int)versionCompiled.minor,
7437 (int)versionCompiled.version,
7438 (int)versionCompiled.revision);
7439 }
7440 else
7441 {
7442 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7443 WLAN_MODULE_NAME,
7444 (int)versionReported.major,
7445 (int)versionReported.minor,
7446 (int)versionReported.version,
7447 (int)versionReported.revision);
7448 }
7449
7450 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7451 versionString,
7452 sizeof(versionString));
7453 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7454 {
7455 hddLog(VOS_TRACE_LEVEL_FATAL,
7456 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007457 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007458 break;
7459 }
7460
7461 pr_info("%s: WCNSS software version %s\n",
7462 WLAN_MODULE_NAME, versionString);
7463
7464 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7465 versionString,
7466 sizeof(versionString));
7467 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7468 {
7469 hddLog(VOS_TRACE_LEVEL_FATAL,
7470 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007471 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007472 break;
7473 }
7474
7475 pr_info("%s: WCNSS hardware version %s\n",
7476 WLAN_MODULE_NAME, versionString);
7477
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007478 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7479 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007480 send the message only if it the riva is 1.1
7481 minor numbers for different riva branches:
7482 0 -> (1.0)Mainline Build
7483 1 -> (1.1)Mainline Build
7484 2->(1.04) Stability Build
7485 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007486 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007487 ((versionReported.minor>=1) && (versionReported.version>=1)))
7488 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7489 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007490
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007491 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007492 {
7493#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7494 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7495 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7496#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007497 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7498 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7499 {
7500 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7501 }
7502
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007503 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007504 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007505
7506 } while (0);
7507
7508}
7509
7510/**---------------------------------------------------------------------------
7511
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307512 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7513
7514 \param - pHddCtx - Pointer to the hdd context
7515
7516 \return - true if hardware supports 5GHz
7517
7518 --------------------------------------------------------------------------*/
7519static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7520{
7521 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7522 * then hardware support 5Ghz.
7523 */
7524 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7525 {
7526 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7527 return true;
7528 }
7529 else
7530 {
7531 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7532 __func__);
7533 return false;
7534 }
7535}
7536
7537
7538/**---------------------------------------------------------------------------
7539
Jeff Johnson295189b2012-06-20 16:38:30 -07007540 \brief hdd_wlan_startup() - HDD init function
7541
7542 This is the driver startup code executed once a WLAN device has been detected
7543
7544 \param - dev - Pointer to the underlying device
7545
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007546 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007547
7548 --------------------------------------------------------------------------*/
7549
7550int hdd_wlan_startup(struct device *dev )
7551{
7552 VOS_STATUS status;
7553 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007554 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007555 hdd_context_t *pHddCtx = NULL;
7556 v_CONTEXT_t pVosContext= NULL;
7557#ifdef WLAN_BTAMP_FEATURE
7558 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7559 WLANBAP_ConfigType btAmpConfig;
7560 hdd_config_t *pConfig;
7561#endif
7562 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007563 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007564
7565 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007566 /*
7567 * cfg80211: wiphy allocation
7568 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307569 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007570
7571 if(wiphy == NULL)
7572 {
7573 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007574 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007575 }
7576
7577 pHddCtx = wiphy_priv(wiphy);
7578
Jeff Johnson295189b2012-06-20 16:38:30 -07007579 //Initialize the adapter context to zeros.
7580 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7581
Jeff Johnson295189b2012-06-20 16:38:30 -07007582 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007583 hdd_prevent_suspend();
7584 pHddCtx->isLoadUnloadInProgress = TRUE;
7585
7586 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7587
7588 /*Get vos context here bcoz vos_open requires it*/
7589 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7590
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007591 if(pVosContext == NULL)
7592 {
7593 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7594 goto err_free_hdd_context;
7595 }
7596
Jeff Johnson295189b2012-06-20 16:38:30 -07007597 //Save the Global VOSS context in adapter context for future.
7598 pHddCtx->pvosContext = pVosContext;
7599
7600 //Save the adapter context in global context for future.
7601 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7602
Jeff Johnson295189b2012-06-20 16:38:30 -07007603 pHddCtx->parent_dev = dev;
7604
7605 init_completion(&pHddCtx->full_pwr_comp_var);
7606 init_completion(&pHddCtx->standby_comp_var);
7607 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007608 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007609 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307610 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007611
7612#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007613 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007614#else
7615 init_completion(&pHddCtx->driver_crda_req);
7616#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007617
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307618 spin_lock_init(&pHddCtx->schedScan_lock);
7619
Jeff Johnson295189b2012-06-20 16:38:30 -07007620 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7621
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307622#ifdef FEATURE_WLAN_TDLS
7623 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7624 * invoked by other instances also) to protect the concurrent
7625 * access for the Adapters by TDLS module.
7626 */
7627 mutex_init(&pHddCtx->tdls_lock);
7628#endif
7629
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307630 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007631 // Load all config first as TL config is needed during vos_open
7632 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7633 if(pHddCtx->cfg_ini == NULL)
7634 {
7635 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7636 goto err_free_hdd_context;
7637 }
7638
7639 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7640
7641 // Read and parse the qcom_cfg.ini file
7642 status = hdd_parse_config_ini( pHddCtx );
7643 if ( VOS_STATUS_SUCCESS != status )
7644 {
7645 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7646 __func__, WLAN_INI_FILE);
7647 goto err_config;
7648 }
7649
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307650 /* INI has been read, initialise the configuredMcastBcastFilter with
7651 * INI value as this will serve as the default value
7652 */
7653 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7654 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7655 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307656
7657 if (false == hdd_is_5g_supported(pHddCtx))
7658 {
7659 //5Ghz is not supported.
7660 if (1 != pHddCtx->cfg_ini->nBandCapability)
7661 {
7662 hddLog(VOS_TRACE_LEVEL_INFO,
7663 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7664 pHddCtx->cfg_ini->nBandCapability = 1;
7665 }
7666 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307667
7668 /* If SNR Monitoring is enabled, FW has to parse all beacons
7669 * for calcaluting and storing the average SNR, so set Nth beacon
7670 * filter to 1 to enable FW to parse all the beaocons
7671 */
7672 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7673 {
7674 /* The log level is deliberately set to WARN as overriding
7675 * nthBeaconFilter to 1 will increase power cosumption and this
7676 * might just prove helpful to detect the power issue.
7677 */
7678 hddLog(VOS_TRACE_LEVEL_WARN,
7679 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7680 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7681 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007682 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307683 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007684 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307685 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007686 {
7687 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307688 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7689 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007690 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007691
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007692 // Update VOS trace levels based upon the cfg.ini
7693 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7694 pHddCtx->cfg_ini->vosTraceEnableBAP);
7695 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7696 pHddCtx->cfg_ini->vosTraceEnableTL);
7697 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7698 pHddCtx->cfg_ini->vosTraceEnableWDI);
7699 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7700 pHddCtx->cfg_ini->vosTraceEnableHDD);
7701 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7702 pHddCtx->cfg_ini->vosTraceEnableSME);
7703 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7704 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307705 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7706 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007707 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7708 pHddCtx->cfg_ini->vosTraceEnableWDA);
7709 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7710 pHddCtx->cfg_ini->vosTraceEnableSYS);
7711 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7712 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007713 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7714 pHddCtx->cfg_ini->vosTraceEnableSAP);
7715 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7716 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007717
Jeff Johnson295189b2012-06-20 16:38:30 -07007718 // Update WDI trace levels based upon the cfg.ini
7719 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7720 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7721 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7722 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7723 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7724 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7725 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7726 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007727
Jeff Johnson88ba7742013-02-27 14:36:02 -08007728 if (VOS_FTM_MODE == hdd_get_conparam())
7729 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007730 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7731 {
7732 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7733 goto err_free_hdd_context;
7734 }
7735 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7736 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007737 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007738
Jeff Johnson88ba7742013-02-27 14:36:02 -08007739 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007740 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7741 {
7742 status = vos_watchdog_open(pVosContext,
7743 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7744
7745 if(!VOS_IS_STATUS_SUCCESS( status ))
7746 {
7747 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307748 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007749 }
7750 }
7751
7752 pHddCtx->isLogpInProgress = FALSE;
7753 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7754
Jeff Johnson295189b2012-06-20 16:38:30 -07007755 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7756 if(!VOS_IS_STATUS_SUCCESS(status))
7757 {
7758 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007759 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007760 }
7761
Amar Singhala49cbc52013-10-08 18:37:44 -07007762#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007763 /* initialize the NV module. This is required so that
7764 we can initialize the channel information in wiphy
7765 from the NV.bin data. The channel information in
7766 wiphy needs to be initialized before wiphy registration */
7767
7768 status = vos_nv_open();
7769 if (!VOS_IS_STATUS_SUCCESS(status))
7770 {
7771 /* NV module cannot be initialized */
7772 hddLog( VOS_TRACE_LEVEL_FATAL,
7773 "%s: vos_nv_open failed", __func__);
7774 goto err_clkvote;
7775 }
7776
7777 status = vos_init_wiphy_from_nv_bin();
7778 if (!VOS_IS_STATUS_SUCCESS(status))
7779 {
7780 /* NV module cannot be initialized */
7781 hddLog( VOS_TRACE_LEVEL_FATAL,
7782 "%s: vos_init_wiphy failed", __func__);
7783 goto err_vos_nv_close;
7784 }
7785
Amar Singhala49cbc52013-10-08 18:37:44 -07007786 /* registration of wiphy dev with cfg80211 */
7787 if (0 > wlan_hdd_cfg80211_register(wiphy))
7788 {
7789 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007790 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007791 }
7792#endif
7793
Jeff Johnson295189b2012-06-20 16:38:30 -07007794 status = vos_open( &pVosContext, 0);
7795 if ( !VOS_IS_STATUS_SUCCESS( status ))
7796 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007797 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007798 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007799 }
7800
Jeff Johnson295189b2012-06-20 16:38:30 -07007801 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7802
7803 if ( NULL == pHddCtx->hHal )
7804 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007805 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007806 goto err_vosclose;
7807 }
7808
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007809 status = vos_preStart( pHddCtx->pvosContext );
7810 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7811 {
7812 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7813 goto err_vosclose;
7814 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007815
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007816 /* Note that the vos_preStart() sequence triggers the cfg download.
7817 The cfg download must occur before we update the SME config
7818 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007819 status = hdd_set_sme_config( pHddCtx );
7820
7821 if ( VOS_STATUS_SUCCESS != status )
7822 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007823 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7824 goto err_vosclose;
7825 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007826
7827 //Initialize the WMM module
7828 status = hdd_wmm_init(pHddCtx);
7829 if (!VOS_IS_STATUS_SUCCESS(status))
7830 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007831 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007832 goto err_vosclose;
7833 }
7834
Jeff Johnson295189b2012-06-20 16:38:30 -07007835 /* In the integrated architecture we update the configuration from
7836 the INI file and from NV before vOSS has been started so that
7837 the final contents are available to send down to the cCPU */
7838
Arif Hussain66559122013-11-21 10:11:40 -08007839 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
7840 {
7841 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
7842 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
7843 __func__, enable_dfs_chan_scan);
7844 }
7845 if (0 == enable_11d || 1 == enable_11d)
7846 {
7847 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
7848 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
7849 __func__, enable_11d);
7850 }
7851
Jeff Johnson295189b2012-06-20 16:38:30 -07007852 // Apply the cfg.ini to cfg.dat
7853 if (FALSE == hdd_update_config_dat(pHddCtx))
7854 {
7855 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7856 goto err_vosclose;
7857 }
7858
7859 // Apply the NV to cfg.dat
7860 /* Prima Update MAC address only at here */
7861 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7862 {
7863#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7864 /* There was not a valid set of MAC Addresses in NV. See if the
7865 default addresses were modified by the cfg.ini settings. If so,
7866 we'll use them, but if not, we'll autogenerate a set of MAC
7867 addresses based upon the device serial number */
7868
7869 static const v_MACADDR_t default_address =
7870 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7871 unsigned int serialno;
7872 int i;
7873
7874 serialno = wcnss_get_serial_number();
7875 if ((0 != serialno) &&
7876 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7877 sizeof(default_address))))
7878 {
7879 /* cfg.ini has the default address, invoke autogen logic */
7880
7881 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7882 bytes of the serial number that can be used to generate
7883 the other 3 bytes of the MAC address. Mask off all but
7884 the lower 3 bytes (this will also make sure we don't
7885 overflow in the next step) */
7886 serialno &= 0x00FFFFFF;
7887
7888 /* we need a unique address for each session */
7889 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7890
7891 /* autogen all addresses */
7892 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7893 {
7894 /* start with the entire default address */
7895 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7896 /* then replace the lower 3 bytes */
7897 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7898 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7899 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7900
7901 serialno++;
7902 }
7903
7904 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7905 MAC_ADDRESS_STR,
7906 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7907 }
7908 else
7909#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7910 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007911 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007912 "%s: Invalid MAC address in NV, using MAC from ini file "
7913 MAC_ADDRESS_STR, __func__,
7914 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7915 }
7916 }
7917 {
7918 eHalStatus halStatus;
7919 // Set the MAC Address
7920 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7921 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7922 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7923 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7924
7925 if (!HAL_STATUS_SUCCESS( halStatus ))
7926 {
7927 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7928 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007929 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007930 }
7931 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007932
7933 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7934 Note: Firmware image will be read and downloaded inside vos_start API */
7935 status = vos_start( pHddCtx->pvosContext );
7936 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7937 {
7938 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7939 goto err_vosclose;
7940 }
7941
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007942 /* Exchange capability info between Host and FW and also get versioning info from FW */
7943 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007944
7945 status = hdd_post_voss_start_config( pHddCtx );
7946 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7947 {
7948 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7949 __func__);
7950 goto err_vosstop;
7951 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007952
7953#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307954 wlan_hdd_cfg80211_update_reg_info( wiphy );
7955
7956 /* registration of wiphy dev with cfg80211 */
7957 if (0 > wlan_hdd_cfg80211_register(wiphy))
7958 {
7959 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7960 goto err_vosstop;
7961 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007962#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007963
Jeff Johnson295189b2012-06-20 16:38:30 -07007964 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7965 {
7966 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7967 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7968 }
7969 else
7970 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007971 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7972 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7973 if (pAdapter != NULL)
7974 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307975 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007976 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307977 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7978 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7979 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007980
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307981 /* Generate the P2P Device Address. This consists of the device's
7982 * primary MAC address with the locally administered bit set.
7983 */
7984 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007985 }
7986 else
7987 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307988 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7989 if (p2p_dev_addr != NULL)
7990 {
7991 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7992 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7993 }
7994 else
7995 {
7996 hddLog(VOS_TRACE_LEVEL_FATAL,
7997 "%s: Failed to allocate mac_address for p2p_device",
7998 __func__);
7999 goto err_close_adapter;
8000 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008001 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008002
8003 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8004 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8005 if ( NULL == pP2pAdapter )
8006 {
8007 hddLog(VOS_TRACE_LEVEL_FATAL,
8008 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008009 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008010 goto err_close_adapter;
8011 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008012 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008013 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008014
8015 if( pAdapter == NULL )
8016 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008017 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8018 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008019 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008020
Arif Hussain66559122013-11-21 10:11:40 -08008021 if (country_code)
8022 {
8023 eHalStatus ret;
8024 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8025#ifndef CONFIG_ENABLE_LINUX_REG
8026 hdd_checkandupdate_phymode(pAdapter, country_code);
8027#endif
8028 ret = sme_ChangeCountryCode(pHddCtx->hHal, NULL,
8029 country_code,
8030 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308031 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008032 if (eHAL_STATUS_SUCCESS == ret)
8033 {
8034 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8035 "%s: SME Change Country code from module param fail ret=%d",
8036 __func__, ret);
8037 }
8038 else
8039 {
8040 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module country code set to %c%c",
8041 __func__, country_code[0], country_code[1]);
8042 }
8043 }
8044
Jeff Johnson295189b2012-06-20 16:38:30 -07008045#ifdef WLAN_BTAMP_FEATURE
8046 vStatus = WLANBAP_Open(pVosContext);
8047 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8048 {
8049 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8050 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008051 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008052 }
8053
8054 vStatus = BSL_Init(pVosContext);
8055 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8056 {
8057 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8058 "%s: Failed to Init BSL",__func__);
8059 goto err_bap_close;
8060 }
8061 vStatus = WLANBAP_Start(pVosContext);
8062 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8063 {
8064 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8065 "%s: Failed to start TL",__func__);
8066 goto err_bap_close;
8067 }
8068
8069 pConfig = pHddCtx->cfg_ini;
8070 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8071 status = WLANBAP_SetConfig(&btAmpConfig);
8072
8073#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008074
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008075#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8076 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8077 {
8078 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8079 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8080 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8081 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8082 }
8083#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008084#ifdef FEATURE_WLAN_SCAN_PNO
8085 /*SME must send channel update configuration to RIVA*/
8086 sme_UpdateChannelConfig(pHddCtx->hHal);
8087#endif
8088
Jeff Johnson295189b2012-06-20 16:38:30 -07008089 /* Register with platform driver as client for Suspend/Resume */
8090 status = hddRegisterPmOps(pHddCtx);
8091 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8092 {
8093 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8094#ifdef WLAN_BTAMP_FEATURE
8095 goto err_bap_stop;
8096#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008097 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008098#endif //WLAN_BTAMP_FEATURE
8099 }
8100
Yue Ma0d4891e2013-08-06 17:01:45 -07008101 /* Open debugfs interface */
8102 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8103 {
8104 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8105 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008106 }
8107
Jeff Johnson295189b2012-06-20 16:38:30 -07008108 /* Register TM level change handler function to the platform */
8109 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8110 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8111 {
8112 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8113 goto err_unregister_pmops;
8114 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008115
8116 /* register for riva power on lock to platform driver */
8117 if (req_riva_power_on_lock("wlan"))
8118 {
8119 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8120 __func__);
8121 goto err_unregister_pmops;
8122 }
8123
Jeff Johnson295189b2012-06-20 16:38:30 -07008124 // register net device notifier for device change notification
8125 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8126
8127 if(ret < 0)
8128 {
8129 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8130 goto err_free_power_on_lock;
8131 }
8132
8133 //Initialize the nlink service
8134 if(nl_srv_init() != 0)
8135 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308136 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008137 goto err_reg_netdev;
8138 }
8139
Leo Chang4ce1cc52013-10-21 18:27:15 -07008140#ifdef WLAN_KD_READY_NOTIFIER
8141 pHddCtx->kd_nl_init = 1;
8142#endif /* WLAN_KD_READY_NOTIFIER */
8143
Jeff Johnson295189b2012-06-20 16:38:30 -07008144 //Initialize the BTC service
8145 if(btc_activate_service(pHddCtx) != 0)
8146 {
8147 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8148 goto err_nl_srv;
8149 }
8150
8151#ifdef PTT_SOCK_SVC_ENABLE
8152 //Initialize the PTT service
8153 if(ptt_sock_activate_svc(pHddCtx) != 0)
8154 {
8155 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8156 goto err_nl_srv;
8157 }
8158#endif
8159
Jeff Johnson295189b2012-06-20 16:38:30 -07008160 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008161 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008162 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008163 /* Action frame registered in one adapter which will
8164 * applicable to all interfaces
8165 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008166 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008167 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008168
8169 mutex_init(&pHddCtx->sap_lock);
8170
8171 pHddCtx->isLoadUnloadInProgress = FALSE;
8172
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008173#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008174#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8175 /* Initialize the wake lcok */
8176 wake_lock_init(&pHddCtx->rx_wake_lock,
8177 WAKE_LOCK_SUSPEND,
8178 "qcom_rx_wakelock");
8179#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008180 /* Initialize the wake lcok */
8181 wake_lock_init(&pHddCtx->sap_wake_lock,
8182 WAKE_LOCK_SUSPEND,
8183 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008184#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008185
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008186 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8187 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008188
8189 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8190 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308191#ifndef CONFIG_ENABLE_LINUX_REG
8192 /*updating wiphy so that regulatory user hints can be processed*/
8193 if (wiphy)
8194 {
8195 regulatory_hint(wiphy, "00");
8196 }
8197#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008198 // Initialize the restart logic
8199 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308200
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008201 //Register the traffic monitor timer now
8202 if ( pHddCtx->cfg_ini->dynSplitscan)
8203 {
8204 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8205 VOS_TIMER_TYPE_SW,
8206 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8207 (void *)pHddCtx);
8208 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008209 goto success;
8210
8211err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008212#ifdef WLAN_KD_READY_NOTIFIER
8213 nl_srv_exit(pHddCtx->ptt_pid);
8214#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008215 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008216#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008217err_reg_netdev:
8218 unregister_netdevice_notifier(&hdd_netdev_notifier);
8219
8220err_free_power_on_lock:
8221 free_riva_power_on_lock("wlan");
8222
8223err_unregister_pmops:
8224 hddDevTmUnregisterNotifyCallback(pHddCtx);
8225 hddDeregisterPmOps(pHddCtx);
8226
Yue Ma0d4891e2013-08-06 17:01:45 -07008227 hdd_debugfs_exit(pHddCtx);
8228
Jeff Johnson295189b2012-06-20 16:38:30 -07008229#ifdef WLAN_BTAMP_FEATURE
8230err_bap_stop:
8231 WLANBAP_Stop(pVosContext);
8232#endif
8233
8234#ifdef WLAN_BTAMP_FEATURE
8235err_bap_close:
8236 WLANBAP_Close(pVosContext);
8237#endif
8238
Jeff Johnson295189b2012-06-20 16:38:30 -07008239err_close_adapter:
8240 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008241
8242#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308243 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008244#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008245
8246err_vosstop:
8247 vos_stop(pVosContext);
8248
Amar Singhala49cbc52013-10-08 18:37:44 -07008249err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008250 status = vos_sched_close( pVosContext );
8251 if (!VOS_IS_STATUS_SUCCESS(status)) {
8252 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8253 "%s: Failed to close VOSS Scheduler", __func__);
8254 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8255 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008256 vos_close(pVosContext );
8257
8258err_wiphy_unregister:
8259
8260#ifdef CONFIG_ENABLE_LINUX_REG
8261 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008262
Amar Singhal0a402232013-10-11 20:57:16 -07008263err_vos_nv_close:
8264
8265 vos_nv_close();
8266
Jeff Johnson295189b2012-06-20 16:38:30 -07008267err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008268#endif
8269
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008270 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008271
8272err_wdclose:
8273 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8274 vos_watchdog_close(pVosContext);
8275
Jeff Johnson295189b2012-06-20 16:38:30 -07008276err_config:
8277 kfree(pHddCtx->cfg_ini);
8278 pHddCtx->cfg_ini= NULL;
8279
8280err_free_hdd_context:
8281 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008282 wiphy_free(wiphy) ;
8283 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008284 VOS_BUG(1);
8285
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008286 if (hdd_is_ssr_required())
8287 {
8288 /* WDI timeout had happened during load, so SSR is needed here */
8289 subsystem_restart("wcnss");
8290 msleep(5000);
8291 }
8292 hdd_set_ssr_required (VOS_FALSE);
8293
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008294 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008295
8296success:
8297 EXIT();
8298 return 0;
8299}
8300
8301/**---------------------------------------------------------------------------
8302
Jeff Johnson32d95a32012-09-10 13:15:23 -07008303 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008304
Jeff Johnson32d95a32012-09-10 13:15:23 -07008305 This is the driver entry point - called in different timeline depending
8306 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008307
8308 \param - None
8309
8310 \return - 0 for success, non zero for failure
8311
8312 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008313static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008314{
8315 VOS_STATUS status;
8316 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008317 struct device *dev = NULL;
8318 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008319#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8320 int max_retries = 0;
8321#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008322
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308323#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8324 vos_wconn_trace_init();
8325#endif
8326
Jeff Johnson295189b2012-06-20 16:38:30 -07008327 ENTER();
8328
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008329#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008330 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008331#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008332
8333 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8334 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8335
8336 //Power Up Libra WLAN card first if not already powered up
8337 status = vos_chipPowerUp(NULL,NULL,NULL);
8338 if (!VOS_IS_STATUS_SUCCESS(status))
8339 {
8340 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8341 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308342#ifdef WLAN_OPEN_SOURCE
8343 wake_lock_destroy(&wlan_wake_lock);
8344#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008345 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008346 }
8347
Jeff Johnson295189b2012-06-20 16:38:30 -07008348#ifdef ANI_BUS_TYPE_PCI
8349
8350 dev = wcnss_wlan_get_device();
8351
8352#endif // ANI_BUS_TYPE_PCI
8353
8354#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008355
8356#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8357 /* wait until WCNSS driver downloads NV */
8358 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8359 msleep(1000);
8360 }
8361 if (max_retries >= 5) {
8362 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308363#ifdef WLAN_OPEN_SOURCE
8364 wake_lock_destroy(&wlan_wake_lock);
8365#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008366 return -ENODEV;
8367 }
8368#endif
8369
Jeff Johnson295189b2012-06-20 16:38:30 -07008370 dev = wcnss_wlan_get_device();
8371#endif // ANI_BUS_TYPE_PLATFORM
8372
8373
8374 do {
8375 if (NULL == dev) {
8376 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8377 ret_status = -1;
8378 break;
8379 }
8380
8381#ifdef MEMORY_DEBUG
8382 vos_mem_init();
8383#endif
8384
8385#ifdef TIMER_MANAGER
8386 vos_timer_manager_init();
8387#endif
8388
8389 /* Preopen VOSS so that it is ready to start at least SAL */
8390 status = vos_preOpen(&pVosContext);
8391
8392 if (!VOS_IS_STATUS_SUCCESS(status))
8393 {
8394 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8395 ret_status = -1;
8396 break;
8397 }
8398
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008399#ifndef MODULE
8400 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8401 */
8402 hdd_set_conparam((v_UINT_t)con_mode);
8403#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008404
8405 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008406 if (hdd_wlan_startup(dev))
8407 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008408 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008409 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008410 vos_preClose( &pVosContext );
8411 ret_status = -1;
8412 break;
8413 }
8414
8415 /* Cancel the vote for XO Core ON
8416 * This is done here for safety purposes in case we re-initialize without turning
8417 * it OFF in any error scenario.
8418 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008419 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008420 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008421 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008422 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8423 {
8424 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008425 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008426 }
8427 } while (0);
8428
8429 if (0 != ret_status)
8430 {
8431 //Assert Deep sleep signal now to put Libra HW in lowest power state
8432 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8433 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8434
8435 //Vote off any PMIC voltage supplies
8436 vos_chipPowerDown(NULL, NULL, NULL);
8437#ifdef TIMER_MANAGER
8438 vos_timer_exit();
8439#endif
8440#ifdef MEMORY_DEBUG
8441 vos_mem_exit();
8442#endif
8443
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008444#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008445 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008446#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008447 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8448 }
8449 else
8450 {
8451 //Send WLAN UP indication to Nlink Service
8452 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8453
8454 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008455 }
8456
8457 EXIT();
8458
8459 return ret_status;
8460}
8461
Jeff Johnson32d95a32012-09-10 13:15:23 -07008462/**---------------------------------------------------------------------------
8463
8464 \brief hdd_module_init() - Init Function
8465
8466 This is the driver entry point (invoked when module is loaded using insmod)
8467
8468 \param - None
8469
8470 \return - 0 for success, non zero for failure
8471
8472 --------------------------------------------------------------------------*/
8473#ifdef MODULE
8474static int __init hdd_module_init ( void)
8475{
8476 return hdd_driver_init();
8477}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008478#else /* #ifdef MODULE */
8479static int __init hdd_module_init ( void)
8480{
8481 /* Driver initialization is delayed to fwpath_changed_handler */
8482 return 0;
8483}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008484#endif /* #ifdef MODULE */
8485
Jeff Johnson295189b2012-06-20 16:38:30 -07008486
8487/**---------------------------------------------------------------------------
8488
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008489 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008490
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008491 This is the driver exit point (invoked when module is unloaded using rmmod
8492 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008493
8494 \param - None
8495
8496 \return - None
8497
8498 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008499static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008500{
8501 hdd_context_t *pHddCtx = NULL;
8502 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008503 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008504
8505 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8506
8507 //Get the global vos context
8508 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8509
8510 if(!pVosContext)
8511 {
8512 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8513 goto done;
8514 }
8515
8516 //Get the HDD context.
8517 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8518
8519 if(!pHddCtx)
8520 {
8521 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8522 }
8523 else
8524 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008525 while(isWDresetInProgress()) {
8526 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8527 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008528 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008529
8530 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8531 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8532 "%s:SSR never completed, fatal error", __func__);
8533 VOS_BUG(0);
8534 }
8535 }
8536
Jeff Johnson295189b2012-06-20 16:38:30 -07008537
8538 pHddCtx->isLoadUnloadInProgress = TRUE;
8539 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8540
8541 //Do all the cleanup before deregistering the driver
8542 hdd_wlan_exit(pHddCtx);
8543 }
8544
Jeff Johnson295189b2012-06-20 16:38:30 -07008545 vos_preClose( &pVosContext );
8546
8547#ifdef TIMER_MANAGER
8548 vos_timer_exit();
8549#endif
8550#ifdef MEMORY_DEBUG
8551 vos_mem_exit();
8552#endif
8553
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308554#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8555 vos_wconn_trace_exit();
8556#endif
8557
Jeff Johnson295189b2012-06-20 16:38:30 -07008558done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008559#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008560 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008561#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008562 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8563}
8564
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008565/**---------------------------------------------------------------------------
8566
8567 \brief hdd_module_exit() - Exit function
8568
8569 This is the driver exit point (invoked when module is unloaded using rmmod)
8570
8571 \param - None
8572
8573 \return - None
8574
8575 --------------------------------------------------------------------------*/
8576static void __exit hdd_module_exit(void)
8577{
8578 hdd_driver_exit();
8579}
8580
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008581#ifdef MODULE
8582static int fwpath_changed_handler(const char *kmessage,
8583 struct kernel_param *kp)
8584{
Jeff Johnson76052702013-04-16 13:55:05 -07008585 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008586}
8587
8588static int con_mode_handler(const char *kmessage,
8589 struct kernel_param *kp)
8590{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008591 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008592}
8593#else /* #ifdef MODULE */
8594/**---------------------------------------------------------------------------
8595
Jeff Johnson76052702013-04-16 13:55:05 -07008596 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008597
Jeff Johnson76052702013-04-16 13:55:05 -07008598 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008599 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008600 - invoked when module parameter fwpath is modified from userspace to signal
8601 initializing the WLAN driver or when con_mode is modified from userspace
8602 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008603
8604 \return - 0 for success, non zero for failure
8605
8606 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008607static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008608{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008609 int ret_status;
8610
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008611 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008612 ret_status = hdd_driver_init();
8613 wlan_hdd_inited = ret_status ? 0 : 1;
8614 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008615 }
8616
8617 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008618
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008619 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008620
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008621 ret_status = hdd_driver_init();
8622 wlan_hdd_inited = ret_status ? 0 : 1;
8623 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008624}
8625
Jeff Johnson295189b2012-06-20 16:38:30 -07008626/**---------------------------------------------------------------------------
8627
Jeff Johnson76052702013-04-16 13:55:05 -07008628 \brief fwpath_changed_handler() - Handler Function
8629
8630 Handle changes to the fwpath parameter
8631
8632 \return - 0 for success, non zero for failure
8633
8634 --------------------------------------------------------------------------*/
8635static int fwpath_changed_handler(const char *kmessage,
8636 struct kernel_param *kp)
8637{
8638 int ret;
8639
8640 ret = param_set_copystring(kmessage, kp);
8641 if (0 == ret)
8642 ret = kickstart_driver();
8643 return ret;
8644}
8645
8646/**---------------------------------------------------------------------------
8647
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008648 \brief con_mode_handler() -
8649
8650 Handler function for module param con_mode when it is changed by userspace
8651 Dynamically linked - do nothing
8652 Statically linked - exit and init driver, as in rmmod and insmod
8653
Jeff Johnson76052702013-04-16 13:55:05 -07008654 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008655
Jeff Johnson76052702013-04-16 13:55:05 -07008656 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008657
8658 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008659static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008660{
Jeff Johnson76052702013-04-16 13:55:05 -07008661 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008662
Jeff Johnson76052702013-04-16 13:55:05 -07008663 ret = param_set_int(kmessage, kp);
8664 if (0 == ret)
8665 ret = kickstart_driver();
8666 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008667}
8668#endif /* #ifdef MODULE */
8669
8670/**---------------------------------------------------------------------------
8671
Jeff Johnson295189b2012-06-20 16:38:30 -07008672 \brief hdd_get_conparam() -
8673
8674 This is the driver exit point (invoked when module is unloaded using rmmod)
8675
8676 \param - None
8677
8678 \return - tVOS_CON_MODE
8679
8680 --------------------------------------------------------------------------*/
8681tVOS_CON_MODE hdd_get_conparam ( void )
8682{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008683#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008684 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008685#else
8686 return (tVOS_CON_MODE)curr_con_mode;
8687#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008688}
8689void hdd_set_conparam ( v_UINT_t newParam )
8690{
8691 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008692#ifndef MODULE
8693 curr_con_mode = con_mode;
8694#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008695}
8696/**---------------------------------------------------------------------------
8697
8698 \brief hdd_softap_sta_deauth() - function
8699
8700 This to take counter measure to handle deauth req from HDD
8701
8702 \param - pAdapter - Pointer to the HDD
8703
8704 \param - enable - boolean value
8705
8706 \return - None
8707
8708 --------------------------------------------------------------------------*/
8709
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008710VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008711{
Jeff Johnson295189b2012-06-20 16:38:30 -07008712 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008713 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008714
8715 ENTER();
8716
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008717 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8718 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008719
8720 //Ignore request to deauth bcmc station
8721 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008722 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008723
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008724 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008725
8726 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008727 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008728}
8729
8730/**---------------------------------------------------------------------------
8731
8732 \brief hdd_softap_sta_disassoc() - function
8733
8734 This to take counter measure to handle deauth req from HDD
8735
8736 \param - pAdapter - Pointer to the HDD
8737
8738 \param - enable - boolean value
8739
8740 \return - None
8741
8742 --------------------------------------------------------------------------*/
8743
8744void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8745{
8746 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8747
8748 ENTER();
8749
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308750 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008751
8752 //Ignore request to disassoc bcmc station
8753 if( pDestMacAddress[0] & 0x1 )
8754 return;
8755
8756 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8757}
8758
8759void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8760{
8761 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8762
8763 ENTER();
8764
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308765 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008766
8767 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8768}
8769
Jeff Johnson295189b2012-06-20 16:38:30 -07008770/**---------------------------------------------------------------------------
8771 *
8772 * \brief hdd_get__concurrency_mode() -
8773 *
8774 *
8775 * \param - None
8776 *
8777 * \return - CONCURRENCY MODE
8778 *
8779 * --------------------------------------------------------------------------*/
8780tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8781{
8782 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8783 hdd_context_t *pHddCtx;
8784
8785 if (NULL != pVosContext)
8786 {
8787 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8788 if (NULL != pHddCtx)
8789 {
8790 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8791 }
8792 }
8793
8794 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008795 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008796 return VOS_STA;
8797}
8798
8799/* Decide whether to allow/not the apps power collapse.
8800 * Allow apps power collapse if we are in connected state.
8801 * if not, allow only if we are in IMPS */
8802v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8803{
8804 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008805 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008806 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008807 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8808 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8809 hdd_adapter_t *pAdapter = NULL;
8810 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008811 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008812
Jeff Johnson295189b2012-06-20 16:38:30 -07008813 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8814 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008815
Yathish9f22e662012-12-10 14:21:35 -08008816 concurrent_state = hdd_get_concurrency_mode();
8817
8818#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8819 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8820 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8821 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8822 return TRUE;
8823#endif
8824
Jeff Johnson295189b2012-06-20 16:38:30 -07008825 /*loop through all adapters. TBD fix for Concurrency */
8826 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8827 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8828 {
8829 pAdapter = pAdapterNode->pAdapter;
8830 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8831 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8832 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008833 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008834 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008835 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008836 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8837 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008838 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008839 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008840 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8841 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008842 return FALSE;
8843 }
8844 }
8845 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8846 pAdapterNode = pNext;
8847 }
8848 return TRUE;
8849}
8850
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008851/* Decides whether to send suspend notification to Riva
8852 * if any adapter is in BMPS; then it is required */
8853v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8854{
8855 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8856 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8857
8858 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8859 {
8860 return TRUE;
8861 }
8862 return FALSE;
8863}
8864
Jeff Johnson295189b2012-06-20 16:38:30 -07008865void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8866{
8867 switch(mode)
8868 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008869 case VOS_STA_MODE:
8870 case VOS_P2P_CLIENT_MODE:
8871 case VOS_P2P_GO_MODE:
8872 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008873 pHddCtx->concurrency_mode |= (1 << mode);
8874 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008875 break;
8876 default:
8877 break;
8878
8879 }
8880 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8881 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8882}
8883
8884
8885void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8886{
8887 switch(mode)
8888 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008889 case VOS_STA_MODE:
8890 case VOS_P2P_CLIENT_MODE:
8891 case VOS_P2P_GO_MODE:
8892 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008893 pHddCtx->no_of_sessions[mode]--;
8894 if (!(pHddCtx->no_of_sessions[mode]))
8895 pHddCtx->concurrency_mode &= (~(1 << mode));
8896 break;
8897 default:
8898 break;
8899 }
8900 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8901 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8902}
8903
Jeff Johnsone7245742012-09-05 17:12:55 -07008904/**---------------------------------------------------------------------------
8905 *
8906 * \brief wlan_hdd_restart_init
8907 *
8908 * This function initalizes restart timer/flag. An internal function.
8909 *
8910 * \param - pHddCtx
8911 *
8912 * \return - None
8913 *
8914 * --------------------------------------------------------------------------*/
8915
8916static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8917{
8918 /* Initialize */
8919 pHddCtx->hdd_restart_retries = 0;
8920 atomic_set(&pHddCtx->isRestartInProgress, 0);
8921 vos_timer_init(&pHddCtx->hdd_restart_timer,
8922 VOS_TIMER_TYPE_SW,
8923 wlan_hdd_restart_timer_cb,
8924 pHddCtx);
8925}
8926/**---------------------------------------------------------------------------
8927 *
8928 * \brief wlan_hdd_restart_deinit
8929 *
8930 * This function cleans up the resources used. An internal function.
8931 *
8932 * \param - pHddCtx
8933 *
8934 * \return - None
8935 *
8936 * --------------------------------------------------------------------------*/
8937
8938static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8939{
8940
8941 VOS_STATUS vos_status;
8942 /* Block any further calls */
8943 atomic_set(&pHddCtx->isRestartInProgress, 1);
8944 /* Cleanup */
8945 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8946 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008947 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008948 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8949 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008950 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008951
8952}
8953
8954/**---------------------------------------------------------------------------
8955 *
8956 * \brief wlan_hdd_framework_restart
8957 *
8958 * This function uses a cfg80211 API to start a framework initiated WLAN
8959 * driver module unload/load.
8960 *
8961 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8962 *
8963 *
8964 * \param - pHddCtx
8965 *
8966 * \return - VOS_STATUS_SUCCESS: Success
8967 * VOS_STATUS_E_EMPTY: Adapter is Empty
8968 * VOS_STATUS_E_NOMEM: No memory
8969
8970 * --------------------------------------------------------------------------*/
8971
8972static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8973{
8974 VOS_STATUS status = VOS_STATUS_SUCCESS;
8975 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008976 int len = (sizeof (struct ieee80211_mgmt));
8977 struct ieee80211_mgmt *mgmt = NULL;
8978
8979 /* Prepare the DEAUTH managment frame with reason code */
8980 mgmt = kzalloc(len, GFP_KERNEL);
8981 if(mgmt == NULL)
8982 {
8983 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8984 "%s: memory allocation failed (%d bytes)", __func__, len);
8985 return VOS_STATUS_E_NOMEM;
8986 }
8987 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008988
8989 /* Iterate over all adapters/devices */
8990 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8991 do
8992 {
8993 if( (status == VOS_STATUS_SUCCESS) &&
8994 pAdapterNode &&
8995 pAdapterNode->pAdapter)
8996 {
8997 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8998 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8999 pAdapterNode->pAdapter->dev->name,
9000 pAdapterNode->pAdapter->device_mode,
9001 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009002 /*
9003 * CFG80211 event to restart the driver
9004 *
9005 * 'cfg80211_send_unprot_deauth' sends a
9006 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9007 * of SME(Linux Kernel) state machine.
9008 *
9009 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9010 * the driver.
9011 *
9012 */
9013
9014 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009015 }
9016 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9017 pAdapterNode = pNext;
9018 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9019
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009020
9021 /* Free the allocated management frame */
9022 kfree(mgmt);
9023
Jeff Johnsone7245742012-09-05 17:12:55 -07009024 /* Retry until we unload or reach max count */
9025 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9026 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9027
9028 return status;
9029
9030}
9031/**---------------------------------------------------------------------------
9032 *
9033 * \brief wlan_hdd_restart_timer_cb
9034 *
9035 * Restart timer callback. An internal function.
9036 *
9037 * \param - User data:
9038 *
9039 * \return - None
9040 *
9041 * --------------------------------------------------------------------------*/
9042
9043void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9044{
9045 hdd_context_t *pHddCtx = usrDataForCallback;
9046 wlan_hdd_framework_restart(pHddCtx);
9047 return;
9048
9049}
9050
9051
9052/**---------------------------------------------------------------------------
9053 *
9054 * \brief wlan_hdd_restart_driver
9055 *
9056 * This function sends an event to supplicant to restart the WLAN driver.
9057 *
9058 * This function is called from vos_wlanRestart.
9059 *
9060 * \param - pHddCtx
9061 *
9062 * \return - VOS_STATUS_SUCCESS: Success
9063 * VOS_STATUS_E_EMPTY: Adapter is Empty
9064 * VOS_STATUS_E_ALREADY: Request already in progress
9065
9066 * --------------------------------------------------------------------------*/
9067VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9068{
9069 VOS_STATUS status = VOS_STATUS_SUCCESS;
9070
9071 /* A tight check to make sure reentrancy */
9072 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9073 {
9074 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9075 "%s: WLAN restart is already in progress", __func__);
9076
9077 return VOS_STATUS_E_ALREADY;
9078 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009079 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009080#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009081 wcnss_reset_intr();
9082#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009083
Jeff Johnsone7245742012-09-05 17:12:55 -07009084 return status;
9085}
9086
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009087/*
9088 * API to find if there is any STA or P2P-Client is connected
9089 */
9090VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9091{
9092 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9093}
Jeff Johnsone7245742012-09-05 17:12:55 -07009094
Jeff Johnson295189b2012-06-20 16:38:30 -07009095//Register the module init/exit functions
9096module_init(hdd_module_init);
9097module_exit(hdd_module_exit);
9098
9099MODULE_LICENSE("Dual BSD/GPL");
9100MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9101MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9102
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009103module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9104 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009105
Jeff Johnson76052702013-04-16 13:55:05 -07009106module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009107 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009108
9109module_param(enable_dfs_chan_scan, int,
9110 S_IRUSR | S_IRGRP | S_IROTH);
9111
9112module_param(enable_11d, int,
9113 S_IRUSR | S_IRGRP | S_IROTH);
9114
9115module_param(country_code, charp,
9116 S_IRUSR | S_IRGRP | S_IROTH);