blob: edeae74897b7dd936b83bdfb5525ef01b229492a [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);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001465 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301466 }
1467
1468 return cur_len;
1469}/*End of hdd_populate_user_batch_scan_rsp*/
1470
1471/**---------------------------------------------------------------------------
1472
1473 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1474 scan response data from HDD queue to user space
1475 It does following in detail:
1476 a) if HDD has enough data in its queue then it 1st copies data to user
1477 space and then send get batch scan indication message to FW. In this
1478 case it does not wait on any event and batch scan response data will
1479 be populated in HDD response queue in MC thread context after receiving
1480 indication from FW
1481 b) else send get batch scan indication message to FW and wait on an event
1482 which will be set once HDD receives complete batch scan response from
1483 FW and then this function returns batch scan response to user space
1484
1485 \param - pAdapter Pointer to HDD adapter
1486 \param - pPrivData Pointer to priv_data
1487
1488 \return - 0 for success -EFAULT for failure
1489
1490 --------------------------------------------------------------------------*/
1491
1492int hdd_return_batch_scan_rsp_to_user
1493(
1494 hdd_adapter_t* pAdapter,
1495 hdd_priv_data_t *pPrivData,
1496 tANI_U8 *command
1497)
1498{
1499 tANI_U8 *pDest;
1500 tANI_U32 count = 0;
1501 tANI_U32 len = 0;
1502 tANI_U32 cur_len = 0;
1503 tANI_U32 rem_len = 0;
1504 eHalStatus halStatus;
1505 unsigned long rc;
1506 tSirTriggerBatchScanResultInd *pReq;
1507
1508 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1509 pReq->param = 0;/*batch scan client*/
1510 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1511 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1512
1513 cur_len = pPrivData->used_len;
1514 if (pPrivData->total_len > pPrivData->used_len)
1515 {
1516 rem_len = pPrivData->total_len - pPrivData->used_len;
1517 }
1518 else
1519 {
1520 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1521 "%s: Invalid user data buffer total_len %d used_len %d",
1522 __func__, pPrivData->total_len, pPrivData->used_len);
1523 return -EFAULT;
1524 }
1525
1526 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1527 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1528 cur_len, rem_len);
1529 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1530
1531 /*enough scan result available in cache to return to user space or
1532 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001533 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301534 {
1535 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1536 halStatus = sme_TriggerBatchScanResultInd(
1537 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1538 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1539 pAdapter);
1540 if ( eHAL_STATUS_SUCCESS == halStatus )
1541 {
1542 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1543 {
1544 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1545 rc = wait_for_completion_timeout(
1546 &pAdapter->hdd_get_batch_scan_req_var,
1547 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1548 if (0 == rc)
1549 {
1550 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1551 "%s: Timeout waiting to fetch batch scan rsp from fw",
1552 __func__);
1553 return -EFAULT;
1554 }
1555 }
1556
1557 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001558 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301559 pDest += len;
1560 cur_len += len;
1561
1562 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1563 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1564 cur_len, rem_len);
1565 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1566
1567 count = 0;
1568 len = (len - pPrivData->used_len);
1569 pDest = (command + pPrivData->used_len);
1570 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001571 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301572 while(count < len)
1573 {
1574 printk("%c", *(pDest + count));
1575 count++;
1576 }
1577 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1578 "%s: copy %d data to user buffer", __func__, len);
1579 if (copy_to_user(pPrivData->buf, pDest, len))
1580 {
1581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1582 "%s: failed to copy data to user buffer", __func__);
1583 return -EFAULT;
1584 }
1585 }
1586 else
1587 {
1588 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1589 "sme_GetBatchScanScan returned failure halStatus %d",
1590 halStatus);
1591 return -EINVAL;
1592 }
1593 }
1594 else
1595 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301596 count = 0;
1597 len = (len - pPrivData->used_len);
1598 pDest = (command + pPrivData->used_len);
1599 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001600 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301601 while(count < len)
1602 {
1603 printk("%c", *(pDest + count));
1604 count++;
1605 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1607 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301608 if (copy_to_user(pPrivData->buf, pDest, len))
1609 {
1610 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1611 "%s: failed to copy data to user buffer", __func__);
1612 return -EFAULT;
1613 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301614 }
1615
1616 return 0;
1617} /*End of hdd_return_batch_scan_rsp_to_user*/
1618
1619#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1620
Jeff Johnson295189b2012-06-20 16:38:30 -07001621int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1622{
1623 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1624 hdd_priv_data_t priv_data;
1625 tANI_U8 *command = NULL;
1626 int ret = 0;
1627
1628 if (NULL == pAdapter)
1629 {
1630 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001631 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001632 ret = -ENODEV;
1633 goto exit;
1634 }
1635
Jeff Johnsone7245742012-09-05 17:12:55 -07001636 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001637 {
1638 ret = -EINVAL;
1639 goto exit;
1640 }
1641
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001642 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1643 {
1644 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1645 "%s:LOGP in Progress. Ignore!!!", __func__);
1646 ret = -EBUSY;
1647 goto exit;
1648 }
1649
Jeff Johnson295189b2012-06-20 16:38:30 -07001650 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1651 {
1652 ret = -EFAULT;
1653 goto exit;
1654 }
1655
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001656 if (priv_data.total_len <= 0)
1657 {
1658 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1659 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1660 priv_data.total_len);
1661 ret = -EINVAL;
1662 goto exit;
1663 }
1664
1665 /* Allocate +1 for '\0' */
1666 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001667 if (!command)
1668 {
1669 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001670 "%s: failed to allocate memory\n", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001671 ret = -ENOMEM;
1672 goto exit;
1673 }
1674
1675 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1676 {
1677 ret = -EFAULT;
1678 goto exit;
1679 }
1680
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001681 /* Making sure the command is NUL-terminated */
1682 command[priv_data.total_len] = '\0';
1683
Jeff Johnson295189b2012-06-20 16:38:30 -07001684 if ((SIOCDEVPRIVATE + 1) == cmd)
1685 {
1686 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1687
1688 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001689 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001690
1691 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1692 {
1693 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1694 sizeof(tSirMacAddr)))
1695 {
1696 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001697 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001698 ret = -EFAULT;
1699 }
1700 }
Amar Singhal0974e402013-02-12 14:27:46 -08001701 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001702 {
Amar Singhal0974e402013-02-12 14:27:46 -08001703 tANI_U8 *ptr = command ;
Jeff Johnson295189b2012-06-20 16:38:30 -07001704 int ret = 0 ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001705
Jeff Johnson295189b2012-06-20 16:38:30 -07001706 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001707
1708 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001709 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001710 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001711 "%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 -07001712 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001713 ret = hdd_setBand_helper(dev, ptr);
1714 }
Kiet Lamf040f472013-11-20 21:15:23 +05301715 else if(strncmp(command, "SETWMMPS", 8) == 0)
1716 {
1717 tANI_U8 *ptr = command;
1718 ret = hdd_wmmps_helper(pAdapter, ptr);
1719 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001720 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1721 {
1722 char *country_code;
1723
1724 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001725
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001726 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001727 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001728#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05301729 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07001730#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001731 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
1732 (void *)(tSmeChangeCountryCallback)
1733 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05301734 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001735 if (eHAL_STATUS_SUCCESS == ret)
1736 {
1737 ret = wait_for_completion_interruptible_timeout(
1738 &pAdapter->change_country_code,
1739 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
1740 if (0 >= ret)
1741 {
1742 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out",
1743 __func__);
1744 }
1745 }
1746 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07001747 {
1748 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001749 "%s: SME Change Country code fail ret=%d", __func__, ret);
1750 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07001751 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001752
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001753 }
1754 /*
1755 command should be a string having format
1756 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
1757 */
Amar Singhal0974e402013-02-12 14:27:46 -08001758 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001759 {
Amar Singhal0974e402013-02-12 14:27:46 -08001760 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001761
1762 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07001763 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07001764
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08001765 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07001766 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08001767 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
1768 {
1769 int suspend = 0;
1770 tANI_U8 *ptr = (tANI_U8*)command + 15;
1771
1772 suspend = *ptr - '0';
1773 hdd_set_wlan_suspend_mode(suspend);
1774 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08001775#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
1776 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
1777 {
1778 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001779 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001780 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
1781 eHalStatus status = eHAL_STATUS_SUCCESS;
1782
1783 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
1784 value = value + 15;
1785
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001786 /* Convert the value from ascii to integer */
1787 ret = kstrtos8(value, 10, &rssi);
1788 if (ret < 0)
1789 {
1790 /* If the input value is greater than max value of datatype, then also
1791 kstrtou8 fails */
1792 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1793 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07001794 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001795 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1796 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1797 ret = -EINVAL;
1798 goto exit;
1799 }
1800
Srinivas Girigowdade697412013-02-14 16:31:48 -08001801 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001802
Srinivas Girigowdade697412013-02-14 16:31:48 -08001803 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
1804 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
1805 {
1806 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1807 "Neighbor lookup threshold value %d is out of range"
1808 " (Min: %d Max: %d)", lookUpThreshold,
1809 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
1810 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
1811 ret = -EINVAL;
1812 goto exit;
1813 }
1814
1815 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1816 "%s: Received Command to Set Roam trigger"
1817 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
1818
1819 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
1820 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
1821 if (eHAL_STATUS_SUCCESS != status)
1822 {
1823 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1824 "%s: Failed to set roam trigger, try again", __func__);
1825 ret = -EPERM;
1826 goto exit;
1827 }
1828
1829 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
1830 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
1831 }
1832 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
1833 {
1834 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
1835 int rssi = (-1) * lookUpThreshold;
1836 char extra[32];
1837 tANI_U8 len = 0;
1838
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001839 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001840 if (copy_to_user(priv_data.buf, &extra, len + 1))
1841 {
1842 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1843 "%s: failed to copy data to user buffer", __func__);
1844 ret = -EFAULT;
1845 goto exit;
1846 }
1847 }
1848 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
1849 {
1850 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001851 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001852 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001853
Srinivas Girigowdade697412013-02-14 16:31:48 -08001854 /* input refresh period is in terms of seconds */
1855 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
1856 value = value + 18;
1857 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001858 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001859 if (ret < 0)
1860 {
1861 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001862 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001864 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08001865 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001866 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1867 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001868 ret = -EINVAL;
1869 goto exit;
1870 }
1871
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001872 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
1873 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08001874 {
1875 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001876 "Roam scan period value %d is out of range"
1877 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07001878 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
1879 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001880 ret = -EINVAL;
1881 goto exit;
1882 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001883 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001884
1885 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1886 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001887 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001888
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001889 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
1890 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001891 }
1892 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
1893 {
1894 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1895 char extra[32];
1896 tANI_U8 len = 0;
1897
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001898 len = scnprintf(extra, sizeof(extra), "%s %d",
1899 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08001900 /* Returned value is in units of seconds */
1901 if (copy_to_user(priv_data.buf, &extra, len + 1))
1902 {
1903 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1904 "%s: failed to copy data to user buffer", __func__);
1905 ret = -EFAULT;
1906 goto exit;
1907 }
1908 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001909 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
1910 {
1911 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001912 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001913 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001914
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001915 /* input refresh period is in terms of seconds */
1916 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
1917 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001918
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001919 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001920 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001921 if (ret < 0)
1922 {
1923 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001924 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001925 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001926 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001927 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001928 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1929 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1930 ret = -EINVAL;
1931 goto exit;
1932 }
1933
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001934 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
1935 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
1936 {
1937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1938 "Neighbor scan results refresh period value %d is out of range"
1939 " (Min: %d Max: %d)", roamScanRefreshPeriod,
1940 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
1941 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
1942 ret = -EINVAL;
1943 goto exit;
1944 }
1945 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
1946
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001947 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1948 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07001949 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001950
1951 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
1952 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
1953 }
1954 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
1955 {
1956 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
1957 char extra[32];
1958 tANI_U8 len = 0;
1959
Sameer Thalappilb0a30232013-09-27 15:37:48 -07001960 len = scnprintf(extra, sizeof(extra), "%s %d",
1961 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07001962 /* Returned value is in units of seconds */
1963 if (copy_to_user(priv_data.buf, &extra, len + 1))
1964 {
1965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1966 "%s: failed to copy data to user buffer", __func__);
1967 ret = -EFAULT;
1968 goto exit;
1969 }
1970 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07001971#ifdef FEATURE_WLAN_LFR
1972 /* SETROAMMODE */
1973 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
1974 {
1975 tANI_U8 *value = command;
1976 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
1977
1978 /* Move pointer to ahead of SETROAMMODE<delimiter> */
1979 value = value + SIZE_OF_SETROAMMODE + 1;
1980
1981 /* Convert the value from ascii to integer */
1982 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
1983 if (ret < 0)
1984 {
1985 /* If the input value is greater than max value of datatype, then also
1986 kstrtou8 fails */
1987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1988 "%s: kstrtou8 failed range [%d - %d]", __func__,
1989 CFG_LFR_FEATURE_ENABLED_MIN,
1990 CFG_LFR_FEATURE_ENABLED_MAX);
1991 ret = -EINVAL;
1992 goto exit;
1993 }
1994 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
1995 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
1996 {
1997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1998 "Roam Mode value %d is out of range"
1999 " (Min: %d Max: %d)", roamMode,
2000 CFG_LFR_FEATURE_ENABLED_MIN,
2001 CFG_LFR_FEATURE_ENABLED_MAX);
2002 ret = -EINVAL;
2003 goto exit;
2004 }
2005
2006 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2007 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2008 /*
2009 * Note that
2010 * SETROAMMODE 0 is to enable LFR while
2011 * SETROAMMODE 1 is to disable LFR, but
2012 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2013 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2014 */
2015 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2016 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2017 else
2018 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2019
2020 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2021 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2022 }
2023 /* GETROAMMODE */
2024 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2025 {
2026 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2027 char extra[32];
2028 tANI_U8 len = 0;
2029
2030 /*
2031 * roamMode value shall be inverted because the sementics is different.
2032 */
2033 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2034 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2035 else
2036 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2037
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002038 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002039 if (copy_to_user(priv_data.buf, &extra, len + 1))
2040 {
2041 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2042 "%s: failed to copy data to user buffer", __func__);
2043 ret = -EFAULT;
2044 goto exit;
2045 }
2046 }
2047#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002048#endif
2049#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2050 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2051 {
2052 tANI_U8 *value = command;
2053 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2054
2055 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2056 value = value + 13;
2057 /* Convert the value from ascii to integer */
2058 ret = kstrtou8(value, 10, &roamRssiDiff);
2059 if (ret < 0)
2060 {
2061 /* If the input value is greater than max value of datatype, then also
2062 kstrtou8 fails */
2063 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2064 "%s: kstrtou8 failed range [%d - %d]", __func__,
2065 CFG_ROAM_RSSI_DIFF_MIN,
2066 CFG_ROAM_RSSI_DIFF_MAX);
2067 ret = -EINVAL;
2068 goto exit;
2069 }
2070
2071 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2072 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2073 {
2074 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2075 "Roam rssi diff value %d is out of range"
2076 " (Min: %d Max: %d)", roamRssiDiff,
2077 CFG_ROAM_RSSI_DIFF_MIN,
2078 CFG_ROAM_RSSI_DIFF_MAX);
2079 ret = -EINVAL;
2080 goto exit;
2081 }
2082
2083 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2084 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2085
2086 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2087 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2088 }
2089 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2090 {
2091 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2092 char extra[32];
2093 tANI_U8 len = 0;
2094
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002095 len = scnprintf(extra, sizeof(extra), "%s %d",
2096 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002097 if (copy_to_user(priv_data.buf, &extra, len + 1))
2098 {
2099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2100 "%s: failed to copy data to user buffer", __func__);
2101 ret = -EFAULT;
2102 goto exit;
2103 }
2104 }
2105#endif
2106#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2107 else if (strncmp(command, "GETBAND", 7) == 0)
2108 {
2109 int band = -1;
2110 char extra[32];
2111 tANI_U8 len = 0;
2112 hdd_getBand_helper(pHddCtx, &band);
2113
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002114 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002115 if (copy_to_user(priv_data.buf, &extra, len + 1))
2116 {
2117 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2118 "%s: failed to copy data to user buffer", __func__);
2119 ret = -EFAULT;
2120 goto exit;
2121 }
2122 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002123 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2124 {
2125 tANI_U8 *value = command;
2126 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2127 tANI_U8 numChannels = 0;
2128 eHalStatus status = eHAL_STATUS_SUCCESS;
2129
2130 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2131 if (eHAL_STATUS_SUCCESS != status)
2132 {
2133 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2134 "%s: Failed to parse channel list information", __func__);
2135 ret = -EINVAL;
2136 goto exit;
2137 }
2138
2139 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2140 {
2141 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2142 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2143 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2144 ret = -EINVAL;
2145 goto exit;
2146 }
2147 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2148 numChannels);
2149 if (eHAL_STATUS_SUCCESS != status)
2150 {
2151 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2152 "%s: Failed to update channel list information", __func__);
2153 ret = -EINVAL;
2154 goto exit;
2155 }
2156 }
2157 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2158 {
2159 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2160 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002161 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002162 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002163 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002164
2165 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2166 ChannelList, &numChannels ))
2167 {
2168 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2169 "%s: failed to get roam scan channel list", __func__);
2170 ret = -EFAULT;
2171 goto exit;
2172 }
2173 /* output channel list is of the format
2174 [Number of roam scan channels][Channel1][Channel2]... */
2175 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002176 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002177 for (j = 0; (j < numChannels); j++)
2178 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002179 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2180 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002181 }
2182
2183 if (copy_to_user(priv_data.buf, &extra, len + 1))
2184 {
2185 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2186 "%s: failed to copy data to user buffer", __func__);
2187 ret = -EFAULT;
2188 goto exit;
2189 }
2190 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002191 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2192 {
2193 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2194 char extra[32];
2195 tANI_U8 len = 0;
2196
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002197 /* Check if the features OKC/CCX/11R are supported simultaneously,
2198 then this operation is not permitted (return FAILURE) */
2199 if (ccxMode &&
2200 hdd_is_okc_mode_enabled(pHddCtx) &&
2201 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2202 {
2203 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2204 "%s: OKC/CCX/11R are supported simultaneously"
2205 " hence this operation is not permitted!", __func__);
2206 ret = -EPERM;
2207 goto exit;
2208 }
2209
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002210 len = scnprintf(extra, sizeof(extra), "%s %d",
2211 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002212 if (copy_to_user(priv_data.buf, &extra, len + 1))
2213 {
2214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2215 "%s: failed to copy data to user buffer", __func__);
2216 ret = -EFAULT;
2217 goto exit;
2218 }
2219 }
2220 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2221 {
2222 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2223 char extra[32];
2224 tANI_U8 len = 0;
2225
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002226 /* Check if the features OKC/CCX/11R are supported simultaneously,
2227 then this operation is not permitted (return FAILURE) */
2228 if (okcMode &&
2229 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2230 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2231 {
2232 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2233 "%s: OKC/CCX/11R are supported simultaneously"
2234 " hence this operation is not permitted!", __func__);
2235 ret = -EPERM;
2236 goto exit;
2237 }
2238
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002239 len = scnprintf(extra, sizeof(extra), "%s %d",
2240 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002241 if (copy_to_user(priv_data.buf, &extra, len + 1))
2242 {
2243 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2244 "%s: failed to copy data to user buffer", __func__);
2245 ret = -EFAULT;
2246 goto exit;
2247 }
2248 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002249 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002250 {
2251 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2252 char extra[32];
2253 tANI_U8 len = 0;
2254
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002255 len = scnprintf(extra, sizeof(extra), "%s %d",
2256 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002257 if (copy_to_user(priv_data.buf, &extra, len + 1))
2258 {
2259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2260 "%s: failed to copy data to user buffer", __func__);
2261 ret = -EFAULT;
2262 goto exit;
2263 }
2264 }
2265 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2266 {
2267 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2268 char extra[32];
2269 tANI_U8 len = 0;
2270
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002271 len = scnprintf(extra, sizeof(extra), "%s %d",
2272 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002273 if (copy_to_user(priv_data.buf, &extra, len + 1))
2274 {
2275 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2276 "%s: failed to copy data to user buffer", __func__);
2277 ret = -EFAULT;
2278 goto exit;
2279 }
2280 }
2281 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2282 {
2283 tANI_U8 *value = command;
2284 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2285
2286 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2287 value = value + 26;
2288 /* Convert the value from ascii to integer */
2289 ret = kstrtou8(value, 10, &minTime);
2290 if (ret < 0)
2291 {
2292 /* If the input value is greater than max value of datatype, then also
2293 kstrtou8 fails */
2294 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2295 "%s: kstrtou8 failed range [%d - %d]", __func__,
2296 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2297 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2298 ret = -EINVAL;
2299 goto exit;
2300 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002301 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2302 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2303 {
2304 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2305 "scan min channel time value %d is out of range"
2306 " (Min: %d Max: %d)", minTime,
2307 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2308 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2309 ret = -EINVAL;
2310 goto exit;
2311 }
2312
2313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2314 "%s: Received Command to change channel min time = %d", __func__, minTime);
2315
2316 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2317 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2318 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002319 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2320 {
2321 tANI_U8 *value = command;
2322 tANI_U8 channel = 0;
2323 tANI_U8 dwellTime = 0;
2324 tANI_U8 bufLen = 0;
2325 tANI_U8 *buf = NULL;
2326 tSirMacAddr targetApBssid;
2327 eHalStatus status = eHAL_STATUS_SUCCESS;
2328 struct ieee80211_channel chan;
2329 tANI_U8 finalLen = 0;
2330 tANI_U8 *finalBuf = NULL;
2331 tANI_U8 temp = 0;
2332 u64 cookie;
2333 hdd_station_ctx_t *pHddStaCtx = NULL;
2334 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2335
2336 /* if not associated, no need to send action frame */
2337 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2338 {
2339 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2340 ret = -EINVAL;
2341 goto exit;
2342 }
2343
2344 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2345 &dwellTime, &buf, &bufLen);
2346 if (eHAL_STATUS_SUCCESS != status)
2347 {
2348 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2349 "%s: Failed to parse send action frame data", __func__);
2350 ret = -EINVAL;
2351 goto exit;
2352 }
2353
2354 /* if the target bssid is different from currently associated AP,
2355 then no need to send action frame */
2356 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2357 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2358 {
2359 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2360 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002361 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002362 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002363 goto exit;
2364 }
2365
2366 /* if the channel number is different from operating channel then
2367 no need to send action frame */
2368 if (channel != pHddStaCtx->conn_info.operationChannel)
2369 {
2370 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2371 "%s: channel(%d) is different from operating channel(%d)",
2372 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2373 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002374 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002375 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002376 goto exit;
2377 }
2378 chan.center_freq = sme_ChnToFreq(channel);
2379
2380 finalLen = bufLen + 24;
2381 finalBuf = vos_mem_malloc(finalLen);
2382 if (NULL == finalBuf)
2383 {
2384 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2385 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002386 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002387 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002388 goto exit;
2389 }
2390 vos_mem_zero(finalBuf, finalLen);
2391
2392 /* Fill subtype */
2393 temp = SIR_MAC_MGMT_ACTION << 4;
2394 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2395
2396 /* Fill type */
2397 temp = SIR_MAC_MGMT_FRAME;
2398 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2399
2400 /* Fill destination address (bssid of the AP) */
2401 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2402
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002403 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002404 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2405
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002406 /* Fill BSSID (AP mac address) */
2407 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002408
2409 /* Fill received buffer from 24th address */
2410 vos_mem_copy(finalBuf + 24, buf, bufLen);
2411
Jeff Johnson11c33152013-04-16 17:52:40 -07002412 /* done with the parsed buffer */
2413 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002414 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002415
Yue Maf49ba872013-08-19 12:04:25 -07002416 wlan_hdd_action( NULL,
2417#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2418 &(pAdapter->wdev),
2419#else
2420 dev,
2421#endif
2422 &chan, 0,
2423#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2424 NL80211_CHAN_HT20, 1,
2425#endif
2426 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002427 1, &cookie );
2428 vos_mem_free(finalBuf);
2429 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002430 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2431 {
2432 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2433 char extra[32];
2434 tANI_U8 len = 0;
2435
2436 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002437 len = scnprintf(extra, sizeof(extra), "%s %d",
2438 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002439 if (copy_to_user(priv_data.buf, &extra, len + 1))
2440 {
2441 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2442 "%s: failed to copy data to user buffer", __func__);
2443 ret = -EFAULT;
2444 goto exit;
2445 }
2446 }
2447 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2448 {
2449 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002450 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002451
2452 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2453 value = value + 19;
2454 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002455 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002456 if (ret < 0)
2457 {
2458 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002459 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002460 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002461 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002462 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2463 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2464 ret = -EINVAL;
2465 goto exit;
2466 }
2467
2468 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2469 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2470 {
2471 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2472 "lfr mode value %d is out of range"
2473 " (Min: %d Max: %d)", maxTime,
2474 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2475 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2476 ret = -EINVAL;
2477 goto exit;
2478 }
2479
2480 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2481 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2482
2483 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
2484 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2485 }
2486 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2487 {
2488 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2489 char extra[32];
2490 tANI_U8 len = 0;
2491
2492 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002493 len = scnprintf(extra, sizeof(extra), "%s %d",
2494 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002495 if (copy_to_user(priv_data.buf, &extra, len + 1))
2496 {
2497 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2498 "%s: failed to copy data to user buffer", __func__);
2499 ret = -EFAULT;
2500 goto exit;
2501 }
2502 }
2503 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2504 {
2505 tANI_U8 *value = command;
2506 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2507
2508 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2509 value = value + 16;
2510 /* Convert the value from ascii to integer */
2511 ret = kstrtou16(value, 10, &val);
2512 if (ret < 0)
2513 {
2514 /* If the input value is greater than max value of datatype, then also
2515 kstrtou16 fails */
2516 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2517 "%s: kstrtou16 failed range [%d - %d]", __func__,
2518 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2519 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2520 ret = -EINVAL;
2521 goto exit;
2522 }
2523
2524 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2525 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2526 {
2527 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2528 "scan home time value %d is out of range"
2529 " (Min: %d Max: %d)", val,
2530 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2531 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2532 ret = -EINVAL;
2533 goto exit;
2534 }
2535
2536 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2537 "%s: Received Command to change scan home time = %d", __func__, val);
2538
2539 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2540 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2541 }
2542 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2543 {
2544 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2545 char extra[32];
2546 tANI_U8 len = 0;
2547
2548 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002549 len = scnprintf(extra, sizeof(extra), "%s %d",
2550 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002551 if (copy_to_user(priv_data.buf, &extra, len + 1))
2552 {
2553 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2554 "%s: failed to copy data to user buffer", __func__);
2555 ret = -EFAULT;
2556 goto exit;
2557 }
2558 }
2559 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2560 {
2561 tANI_U8 *value = command;
2562 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2563
2564 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2565 value = value + 17;
2566 /* Convert the value from ascii to integer */
2567 ret = kstrtou8(value, 10, &val);
2568 if (ret < 0)
2569 {
2570 /* If the input value is greater than max value of datatype, then also
2571 kstrtou8 fails */
2572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2573 "%s: kstrtou8 failed range [%d - %d]", __func__,
2574 CFG_ROAM_INTRA_BAND_MIN,
2575 CFG_ROAM_INTRA_BAND_MAX);
2576 ret = -EINVAL;
2577 goto exit;
2578 }
2579
2580 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2581 (val > CFG_ROAM_INTRA_BAND_MAX))
2582 {
2583 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2584 "intra band mode value %d is out of range"
2585 " (Min: %d Max: %d)", val,
2586 CFG_ROAM_INTRA_BAND_MIN,
2587 CFG_ROAM_INTRA_BAND_MAX);
2588 ret = -EINVAL;
2589 goto exit;
2590 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2592 "%s: Received Command to change intra band = %d", __func__, val);
2593
2594 pHddCtx->cfg_ini->nRoamIntraBand = val;
2595 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2596 }
2597 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2598 {
2599 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2600 char extra[32];
2601 tANI_U8 len = 0;
2602
2603 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002604 len = scnprintf(extra, sizeof(extra), "%s %d",
2605 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002606 if (copy_to_user(priv_data.buf, &extra, len + 1))
2607 {
2608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2609 "%s: failed to copy data to user buffer", __func__);
2610 ret = -EFAULT;
2611 goto exit;
2612 }
2613 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002614 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2615 {
2616 tANI_U8 *value = command;
2617 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2618
2619 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2620 value = value + 15;
2621 /* Convert the value from ascii to integer */
2622 ret = kstrtou8(value, 10, &nProbes);
2623 if (ret < 0)
2624 {
2625 /* If the input value is greater than max value of datatype, then also
2626 kstrtou8 fails */
2627 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2628 "%s: kstrtou8 failed range [%d - %d]", __func__,
2629 CFG_ROAM_SCAN_N_PROBES_MIN,
2630 CFG_ROAM_SCAN_N_PROBES_MAX);
2631 ret = -EINVAL;
2632 goto exit;
2633 }
2634
2635 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2636 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2637 {
2638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2639 "NProbes value %d is out of range"
2640 " (Min: %d Max: %d)", nProbes,
2641 CFG_ROAM_SCAN_N_PROBES_MIN,
2642 CFG_ROAM_SCAN_N_PROBES_MAX);
2643 ret = -EINVAL;
2644 goto exit;
2645 }
2646
2647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2648 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2649
2650 pHddCtx->cfg_ini->nProbes = nProbes;
2651 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2652 }
2653 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2654 {
2655 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2656 char extra[32];
2657 tANI_U8 len = 0;
2658
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002659 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002660 if (copy_to_user(priv_data.buf, &extra, len + 1))
2661 {
2662 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2663 "%s: failed to copy data to user buffer", __func__);
2664 ret = -EFAULT;
2665 goto exit;
2666 }
2667 }
2668 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2669 {
2670 tANI_U8 *value = command;
2671 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
2672
2673 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2674 /* input value is in units of msec */
2675 value = value + 20;
2676 /* Convert the value from ascii to integer */
2677 ret = kstrtou16(value, 10, &homeAwayTime);
2678 if (ret < 0)
2679 {
2680 /* If the input value is greater than max value of datatype, then also
2681 kstrtou8 fails */
2682 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2683 "%s: kstrtou8 failed range [%d - %d]", __func__,
2684 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2685 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2686 ret = -EINVAL;
2687 goto exit;
2688 }
2689
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002690 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2691 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2692 {
2693 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2694 "homeAwayTime value %d is out of range"
2695 " (Min: %d Max: %d)", homeAwayTime,
2696 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2697 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2698 ret = -EINVAL;
2699 goto exit;
2700 }
2701
2702 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2703 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002704 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2705 {
2706 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2707 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2708 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002709 }
2710 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2711 {
2712 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2713 char extra[32];
2714 tANI_U8 len = 0;
2715
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002716 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002717 if (copy_to_user(priv_data.buf, &extra, len + 1))
2718 {
2719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2720 "%s: failed to copy data to user buffer", __func__);
2721 ret = -EFAULT;
2722 goto exit;
2723 }
2724 }
2725 else if (strncmp(command, "REASSOC", 7) == 0)
2726 {
2727 tANI_U8 *value = command;
2728 tANI_U8 channel = 0;
2729 tSirMacAddr targetApBssid;
2730 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002731#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2732 tCsrHandoffRequest handoffInfo;
2733#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002734 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002735 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2736
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002737 /* if not associated, no need to proceed with reassoc */
2738 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2739 {
2740 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2741 ret = -EINVAL;
2742 goto exit;
2743 }
2744
2745 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
2746 if (eHAL_STATUS_SUCCESS != status)
2747 {
2748 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2749 "%s: Failed to parse reassoc command data", __func__);
2750 ret = -EINVAL;
2751 goto exit;
2752 }
2753
2754 /* if the target bssid is same as currently associated AP,
2755 then no need to proceed with reassoc */
2756 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2757 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2758 {
2759 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
2760 ret = -EINVAL;
2761 goto exit;
2762 }
2763
2764 /* Check channel number is a valid channel number */
2765 if(VOS_STATUS_SUCCESS !=
2766 wlan_hdd_validate_operation_channel(pAdapter, channel))
2767 {
2768 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08002769 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002770 return -EINVAL;
2771 }
2772
2773 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07002774#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
2775 handoffInfo.channel = channel;
2776 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
2777 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
2778#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002779 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002780 else if (strncmp(command, "SETWESMODE", 10) == 0)
2781 {
2782 tANI_U8 *value = command;
2783 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
2784
2785 /* Move pointer to ahead of SETWESMODE<delimiter> */
2786 value = value + 11;
2787 /* Convert the value from ascii to integer */
2788 ret = kstrtou8(value, 10, &wesMode);
2789 if (ret < 0)
2790 {
2791 /* If the input value is greater than max value of datatype, then also
2792 kstrtou8 fails */
2793 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2794 "%s: kstrtou8 failed range [%d - %d]", __func__,
2795 CFG_ENABLE_WES_MODE_NAME_MIN,
2796 CFG_ENABLE_WES_MODE_NAME_MAX);
2797 ret = -EINVAL;
2798 goto exit;
2799 }
2800
2801 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
2802 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
2803 {
2804 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2805 "WES Mode value %d is out of range"
2806 " (Min: %d Max: %d)", wesMode,
2807 CFG_ENABLE_WES_MODE_NAME_MIN,
2808 CFG_ENABLE_WES_MODE_NAME_MAX);
2809 ret = -EINVAL;
2810 goto exit;
2811 }
2812 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2813 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
2814
2815 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
2816 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
2817 }
2818 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
2819 {
2820 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
2821 char extra[32];
2822 tANI_U8 len = 0;
2823
Arif Hussain826d9412013-11-12 16:44:54 -08002824 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07002825 if (copy_to_user(priv_data.buf, &extra, len + 1))
2826 {
2827 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2828 "%s: failed to copy data to user buffer", __func__);
2829 ret = -EFAULT;
2830 goto exit;
2831 }
2832 }
2833#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002834#ifdef FEATURE_WLAN_LFR
2835 else if (strncmp(command, "SETFASTROAM", 11) == 0)
2836 {
2837 tANI_U8 *value = command;
2838 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2839
2840 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2841 value = value + 12;
2842 /* Convert the value from ascii to integer */
2843 ret = kstrtou8(value, 10, &lfrMode);
2844 if (ret < 0)
2845 {
2846 /* If the input value is greater than max value of datatype, then also
2847 kstrtou8 fails */
2848 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2849 "%s: kstrtou8 failed range [%d - %d]", __func__,
2850 CFG_LFR_FEATURE_ENABLED_MIN,
2851 CFG_LFR_FEATURE_ENABLED_MAX);
2852 ret = -EINVAL;
2853 goto exit;
2854 }
2855
2856 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2857 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
2858 {
2859 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2860 "lfr mode value %d is out of range"
2861 " (Min: %d Max: %d)", lfrMode,
2862 CFG_LFR_FEATURE_ENABLED_MIN,
2863 CFG_LFR_FEATURE_ENABLED_MAX);
2864 ret = -EINVAL;
2865 goto exit;
2866 }
2867
2868 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2869 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
2870
2871 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
2872 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
2873 }
2874#endif
2875#ifdef WLAN_FEATURE_VOWIFI_11R
2876 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
2877 {
2878 tANI_U8 *value = command;
2879 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
2880
2881 /* Move pointer to ahead of SETFASTROAM<delimiter> */
2882 value = value + 18;
2883 /* Convert the value from ascii to integer */
2884 ret = kstrtou8(value, 10, &ft);
2885 if (ret < 0)
2886 {
2887 /* If the input value is greater than max value of datatype, then also
2888 kstrtou8 fails */
2889 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2890 "%s: kstrtou8 failed range [%d - %d]", __func__,
2891 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2892 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2893 ret = -EINVAL;
2894 goto exit;
2895 }
2896
2897 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
2898 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
2899 {
2900 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2901 "ft mode value %d is out of range"
2902 " (Min: %d Max: %d)", ft,
2903 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
2904 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
2905 ret = -EINVAL;
2906 goto exit;
2907 }
2908
2909 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2910 "%s: Received Command to change ft mode = %d", __func__, ft);
2911
2912 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
2913 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
2914 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05302915
2916 else if (strncmp(command, "FASTREASSOC", 11) == 0)
2917 {
2918 tANI_U8 *value = command;
2919 tSirMacAddr targetApBssid;
2920 tANI_U8 trigger = 0;
2921 eHalStatus status = eHAL_STATUS_SUCCESS;
2922 hdd_station_ctx_t *pHddStaCtx = NULL;
2923 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2924
2925 /* if not associated, no need to proceed with reassoc */
2926 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2927 {
2928 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2929 ret = -EINVAL;
2930 goto exit;
2931 }
2932
2933 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
2934 if (eHAL_STATUS_SUCCESS != status)
2935 {
2936 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2937 "%s: Failed to parse reassoc command data", __func__);
2938 ret = -EINVAL;
2939 goto exit;
2940 }
2941
2942 /* if the target bssid is same as currently associated AP,
2943 then no need to proceed with reassoc */
2944 if (VOS_TRUE == vos_mem_compare(targetApBssid,
2945 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2946 {
2947 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2948 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
2949 __func__);
2950 ret = -EINVAL;
2951 goto exit;
2952 }
2953
2954 /* Proceed with scan/roam */
2955 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
2956 &targetApBssid[0],
2957 (tSmeFastRoamTrigger)(trigger));
2958 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002959#endif
2960#ifdef FEATURE_WLAN_CCX
2961 else if (strncmp(command, "SETCCXMODE", 10) == 0)
2962 {
2963 tANI_U8 *value = command;
2964 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
2965
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002966 /* Check if the features OKC/CCX/11R are supported simultaneously,
2967 then this operation is not permitted (return FAILURE) */
2968 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2969 hdd_is_okc_mode_enabled(pHddCtx) &&
2970 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2971 {
2972 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2973 "%s: OKC/CCX/11R are supported simultaneously"
2974 " hence this operation is not permitted!", __func__);
2975 ret = -EPERM;
2976 goto exit;
2977 }
2978
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002979 /* Move pointer to ahead of SETCCXMODE<delimiter> */
2980 value = value + 11;
2981 /* Convert the value from ascii to integer */
2982 ret = kstrtou8(value, 10, &ccxMode);
2983 if (ret < 0)
2984 {
2985 /* If the input value is greater than max value of datatype, then also
2986 kstrtou8 fails */
2987 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2988 "%s: kstrtou8 failed range [%d - %d]", __func__,
2989 CFG_CCX_FEATURE_ENABLED_MIN,
2990 CFG_CCX_FEATURE_ENABLED_MAX);
2991 ret = -EINVAL;
2992 goto exit;
2993 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002994 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
2995 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
2996 {
2997 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2998 "Ccx mode value %d is out of range"
2999 " (Min: %d Max: %d)", ccxMode,
3000 CFG_CCX_FEATURE_ENABLED_MIN,
3001 CFG_CCX_FEATURE_ENABLED_MAX);
3002 ret = -EINVAL;
3003 goto exit;
3004 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003005 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3006 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3007
3008 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3009 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3010 }
3011#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003012 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3013 {
3014 tANI_U8 *value = command;
3015 tANI_BOOLEAN roamScanControl = 0;
3016
3017 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3018 value = value + 19;
3019 /* Convert the value from ascii to integer */
3020 ret = kstrtou8(value, 10, &roamScanControl);
3021 if (ret < 0)
3022 {
3023 /* If the input value is greater than max value of datatype, then also
3024 kstrtou8 fails */
3025 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3026 "%s: kstrtou8 failed ", __func__);
3027 ret = -EINVAL;
3028 goto exit;
3029 }
3030
3031 if (0 != roamScanControl)
3032 {
3033 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3034 "roam scan control invalid value = %d",
3035 roamScanControl);
3036 ret = -EINVAL;
3037 goto exit;
3038 }
3039 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3040 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3041
3042 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3043 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003044#ifdef FEATURE_WLAN_OKC
3045 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3046 {
3047 tANI_U8 *value = command;
3048 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3049
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003050 /* Check if the features OKC/CCX/11R are supported simultaneously,
3051 then this operation is not permitted (return FAILURE) */
3052 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3053 hdd_is_okc_mode_enabled(pHddCtx) &&
3054 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3055 {
3056 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3057 "%s: OKC/CCX/11R are supported simultaneously"
3058 " hence this operation is not permitted!", __func__);
3059 ret = -EPERM;
3060 goto exit;
3061 }
3062
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003063 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3064 value = value + 11;
3065 /* Convert the value from ascii to integer */
3066 ret = kstrtou8(value, 10, &okcMode);
3067 if (ret < 0)
3068 {
3069 /* If the input value is greater than max value of datatype, then also
3070 kstrtou8 fails */
3071 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3072 "%s: kstrtou8 failed range [%d - %d]", __func__,
3073 CFG_OKC_FEATURE_ENABLED_MIN,
3074 CFG_OKC_FEATURE_ENABLED_MAX);
3075 ret = -EINVAL;
3076 goto exit;
3077 }
3078
3079 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3080 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3081 {
3082 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3083 "Okc mode value %d is out of range"
3084 " (Min: %d Max: %d)", okcMode,
3085 CFG_OKC_FEATURE_ENABLED_MIN,
3086 CFG_OKC_FEATURE_ENABLED_MAX);
3087 ret = -EINVAL;
3088 goto exit;
3089 }
3090
3091 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3092 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3093
3094 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3095 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003096#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003097 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3098 {
3099 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3100 char extra[32];
3101 tANI_U8 len = 0;
3102
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003103 len = scnprintf(extra, sizeof(extra), "%s %d",
3104 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003105 if (copy_to_user(priv_data.buf, &extra, len + 1))
3106 {
3107 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3108 "%s: failed to copy data to user buffer", __func__);
3109 ret = -EFAULT;
3110 goto exit;
3111 }
3112 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303113#ifdef WLAN_FEATURE_PACKET_FILTERING
3114 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3115 {
3116 tANI_U8 filterType = 0;
3117 tANI_U8 *value = command;
3118
3119 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3120 value = value + 22;
3121
3122 /* Convert the value from ascii to integer */
3123 ret = kstrtou8(value, 10, &filterType);
3124 if (ret < 0)
3125 {
3126 /* If the input value is greater than max value of datatype,
3127 * then also kstrtou8 fails
3128 */
3129 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3130 "%s: kstrtou8 failed range ", __func__);
3131 ret = -EINVAL;
3132 goto exit;
3133 }
3134
3135 if (filterType != 0 && filterType != 1)
3136 {
3137 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3138 "%s: Accepted Values are 0 and 1 ", __func__);
3139 ret = -EINVAL;
3140 goto exit;
3141 }
3142 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3143 pAdapter->sessionId);
3144 }
3145#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303146 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3147 {
3148 char *dhcpPhase;
3149 dhcpPhase = command + 12;
3150 if ('1' == *dhcpPhase)
3151 {
3152 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3153 pAdapter->macAddressCurrent.bytes);
3154 }
3155 else if ('2' == *dhcpPhase)
3156 {
3157 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3158 pAdapter->macAddressCurrent.bytes);
3159 }
3160 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003161 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3162 {
3163 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3164 }
3165 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3166 {
3167 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3168 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303169 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3170 {
3171 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3172 char extra[32];
3173 tANI_U8 len = 0;
3174
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003175 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303176 (int)pCfg->nActiveMaxChnTime);
3177 if (copy_to_user(priv_data.buf, &extra, len + 1))
3178 {
3179 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3180 "%s: failed to copy data to user buffer", __func__);
3181 ret = -EFAULT;
3182 goto exit;
3183 }
3184 ret = len;
3185 }
3186 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3187 {
3188 tANI_U8 *value = command;
3189 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3190 int val = 0, temp;
3191
3192 value = value + 13;
3193 temp = kstrtou32(value, 10, &val);
3194 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3195 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3196 {
3197 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3198 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3199 ret = -EFAULT;
3200 goto exit;
3201 }
3202 pCfg->nActiveMaxChnTime = val;
3203 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003204 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3205 {
3206 tANI_U8 filterType = 0;
3207 tANI_U8 *value;
3208 value = command + 9;
3209
3210 /* Convert the value from ascii to integer */
3211 ret = kstrtou8(value, 10, &filterType);
3212 if (ret < 0)
3213 {
3214 /* If the input value is greater than max value of datatype,
3215 * then also kstrtou8 fails
3216 */
3217 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3218 "%s: kstrtou8 failed range ", __func__);
3219 ret = -EINVAL;
3220 goto exit;
3221 }
3222 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3223 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3224 {
3225 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3226 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3227 " 2-Sink ", __func__);
3228 ret = -EINVAL;
3229 goto exit;
3230 }
3231 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3232 pHddCtx->drvr_miracast = filterType;
3233 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3234 }
Leo Chang614d2072013-08-22 14:59:44 -07003235 else if (strncmp(command, "SETMCRATE", 9) == 0)
3236 {
Leo Chang614d2072013-08-22 14:59:44 -07003237 tANI_U8 *value = command;
3238 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003239 tSirRateUpdateInd *rateUpdate;
3240 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003241
3242 /* Only valid for SAP mode */
3243 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3244 {
3245 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3246 "%s: SAP mode is not running", __func__);
3247 ret = -EFAULT;
3248 goto exit;
3249 }
3250
3251 /* Move pointer to ahead of SETMCRATE<delimiter> */
3252 /* input value is in units of hundred kbps */
3253 value = value + 10;
3254 /* Convert the value from ascii to integer, decimal base */
3255 ret = kstrtouint(value, 10, &targetRate);
3256
Leo Chang1f98cbd2013-10-17 15:03:52 -07003257 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3258 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003259 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003260 hddLog(VOS_TRACE_LEVEL_ERROR,
3261 "%s: SETMCRATE indication alloc fail", __func__);
3262 ret = -EFAULT;
3263 goto exit;
3264 }
3265 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3266
3267 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3268 "MC Target rate %d", targetRate);
3269 /* Ignore unicast */
3270 rateUpdate->ucastDataRate = -1;
3271 rateUpdate->mcastDataRate24GHz = targetRate;
3272 rateUpdate->mcastDataRate5GHz = targetRate;
3273 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3274 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3275 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3276 if (eHAL_STATUS_SUCCESS != status)
3277 {
3278 hddLog(VOS_TRACE_LEVEL_ERROR,
3279 "%s: SET_MC_RATE failed", __func__);
3280 vos_mem_free(rateUpdate);
3281 ret = -EFAULT;
3282 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003283 }
3284 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303285#ifdef FEATURE_WLAN_BATCH_SCAN
3286 else if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
3287 {
3288 char extra[32];
3289 tANI_U8 len = 0;
3290 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
3291
3292 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3293 {
3294 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3295 "%s: Batch scan feature is not supported by FW", __func__);
3296 ret = -EINVAL;
3297 goto exit;
3298 }
3299
3300 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
3301 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode))
3302 {
3303 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3304 "Received WLS_BATCHING_VERSION command in invalid mode %d "
3305 "WLS_BATCHING_VERSION is only allowed in infra STA/P2P client"
3306 " mode",
3307 pAdapter->device_mode);
3308 ret = -EINVAL;
3309 goto exit;
3310 }
3311
Arif Hussain826d9412013-11-12 16:44:54 -08003312 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
Rajeev79dbe4c2013-10-05 11:03:42 +05303313 version);
3314 if (copy_to_user(priv_data.buf, &extra, len + 1))
3315 {
3316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3317 "%s: failed to copy data to user buffer", __func__);
3318 ret = -EFAULT;
3319 goto exit;
3320 }
3321 ret = HDD_BATCH_SCAN_VERSION;
3322 }
3323 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
3324 {
3325 int status;
3326 tANI_U8 *value = (command + 16);
3327 eHalStatus halStatus;
3328 unsigned long rc;
3329 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
3330 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
3331
3332 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3333 {
3334 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3335 "%s: Batch scan feature is not supported by FW", __func__);
3336 ret = -EINVAL;
3337 goto exit;
3338 }
3339
Rajeev Kumar20140c12013-10-21 19:39:02 -07003340
Rajeev79dbe4c2013-10-05 11:03:42 +05303341 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
Rajeev Kumar5286bb92013-12-05 11:52:10 -08003342 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
3343 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
Rajeev79dbe4c2013-10-05 11:03:42 +05303344 {
3345 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003346 "Received WLS_BATCHING SET command in invalid mode %d "
Rajeev79dbe4c2013-10-05 11:03:42 +05303347 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
3348 pAdapter->device_mode);
3349 ret = -EINVAL;
3350 goto exit;
3351 }
3352
Rajeev Kumar20140c12013-10-21 19:39:02 -07003353
Rajeev79dbe4c2013-10-05 11:03:42 +05303354 status = hdd_parse_set_batchscan_command(value, pReq);
3355 if (status)
3356 {
3357 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003358 "Invalid WLS_BATCHING SET command");
Rajeev79dbe4c2013-10-05 11:03:42 +05303359 ret = -EINVAL;
3360 goto exit;
3361 }
Rajeev Kumar20140c12013-10-21 19:39:02 -07003362
3363
Rajeev79dbe4c2013-10-05 11:03:42 +05303364 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
3365 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
3366 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
3367 pAdapter);
3368
3369 if ( eHAL_STATUS_SUCCESS == halStatus )
3370 {
3371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3372 "sme_SetBatchScanReq returned success halStatus %d",
3373 halStatus);
3374 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
3375 {
3376 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
3377 rc = wait_for_completion_timeout(
3378 &pAdapter->hdd_set_batch_scan_req_var,
3379 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
3380 if (0 == rc)
3381 {
3382 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3383 "%s: Timeout waiting for set batch scan to complete",
3384 __func__);
3385 ret = -EINVAL;
3386 goto exit;
3387 }
3388 }
3389 if ( !pRsp->nScansToBatch )
3390 {
3391 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3392 "%s: Received set batch scan failure response from FW",
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003393 __func__);
Rajeev79dbe4c2013-10-05 11:03:42 +05303394 ret = -EINVAL;
3395 goto exit;
3396 }
3397 /*As per the Batch Scan Framework API we should return the MIN of
3398 either MSCAN or the max # of scans firmware can cache*/
3399 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
3400
Rajeev Kumar20140c12013-10-21 19:39:02 -07003401 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
3402
Rajeev79dbe4c2013-10-05 11:03:42 +05303403 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3404 "%s: request MSCAN %d response MSCAN %d ret %d",
3405 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
3406 }
3407 else
3408 {
3409 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3410 "sme_SetBatchScanReq returned failure halStatus %d",
3411 halStatus);
3412 ret = -EINVAL;
3413 goto exit;
3414 }
3415 }
3416 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
3417 {
3418 eHalStatus halStatus;
3419 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
3420 pInd->param = 0;
3421
3422 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3423 {
3424 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3425 "%s: Batch scan feature is not supported by FW", __func__);
3426 ret = -EINVAL;
3427 goto exit;
3428 }
3429
Rajeev Kumar20140c12013-10-21 19:39:02 -07003430 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303431 {
3432 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003433 "Batch scan is not yet enabled batch scan state %d",
3434 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303435 ret = -EINVAL;
3436 goto exit;
3437 }
3438
Rajeev Kumar20140c12013-10-21 19:39:02 -07003439 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
3440
Rajeev79dbe4c2013-10-05 11:03:42 +05303441 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
3442 pAdapter->sessionId);
3443 if ( eHAL_STATUS_SUCCESS == halStatus )
3444 {
3445 ret = 0;
3446 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3447 "sme_StopBatchScanInd returned success halStatus %d",
3448 halStatus);
3449 }
3450 else
3451 {
3452 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3453 "sme_StopBatchScanInd returned failure halStatus %d",
3454 halStatus);
3455 ret = -EINVAL;
3456 goto exit;
3457 }
3458 }
3459 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
3460 {
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003461 tANI_U32 remain_len;
3462
Rajeev79dbe4c2013-10-05 11:03:42 +05303463 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
3464 {
3465 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3466 "%s: Batch scan feature is not supported by FW", __func__);
3467 ret = -EINVAL;
3468 goto exit;
3469 }
3470
Rajeev Kumar20140c12013-10-21 19:39:02 -07003471 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
Rajeev79dbe4c2013-10-05 11:03:42 +05303472 {
3473 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar20140c12013-10-21 19:39:02 -07003474 "Batch scan is not yet enabled could not return results"
3475 "Batch Scan state %d",
3476 pAdapter->batchScanState);
Rajeev79dbe4c2013-10-05 11:03:42 +05303477 ret = -EINVAL;
3478 goto exit;
3479 }
3480
3481 priv_data.used_len = 16;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003482 remain_len = priv_data.total_len - priv_data.used_len;
3483 if (remain_len < priv_data.total_len)
3484 {
3485 /*Clear previous batch scan response data if any*/
3486 vos_mem_zero((tANI_U8 *)(command + priv_data.used_len), remain_len);
3487 }
3488 else
3489 {
3490 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3491 "Invalid total length from user space can't fetch batch"
Jeff Johnson0299d0a2013-10-30 12:37:43 -07003492 " scan response total_len %d used_len %d remain len %d",
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07003493 priv_data.total_len, priv_data.used_len, remain_len);
3494 ret = -EINVAL;
3495 goto exit;
3496 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303497 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, &priv_data, command);
3498 }
3499#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003500#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3501 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3502 {
3503 tANI_U8 *value = command;
3504 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3505 tANI_U8 numChannels = 0;
3506 eHalStatus status = eHAL_STATUS_SUCCESS;
3507
3508 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3509 if (eHAL_STATUS_SUCCESS != status)
3510 {
3511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3512 "%s: Failed to parse channel list information", __func__);
3513 ret = -EINVAL;
3514 goto exit;
3515 }
3516
3517 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3518 {
3519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3520 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3521 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3522 ret = -EINVAL;
3523 goto exit;
3524 }
3525 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3526 ChannelList,
3527 numChannels);
3528 if (eHAL_STATUS_SUCCESS != status)
3529 {
3530 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3531 "%s: Failed to update channel list information", __func__);
3532 ret = -EINVAL;
3533 goto exit;
3534 }
3535 }
3536 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3537 {
3538 tANI_U8 *value = command;
3539 char extra[128] = {0};
3540 int len = 0;
3541 tANI_U8 tid = 0;
3542 hdd_station_ctx_t *pHddStaCtx = NULL;
3543 tAniTrafStrmMetrics tsmMetrics;
3544 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3545
3546 /* if not associated, return error */
3547 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3548 {
3549 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3550 ret = -EINVAL;
3551 goto exit;
3552 }
3553
3554 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3555 value = value + 12;
3556 /* Convert the value from ascii to integer */
3557 ret = kstrtou8(value, 10, &tid);
3558 if (ret < 0)
3559 {
3560 /* If the input value is greater than max value of datatype, then also
3561 kstrtou8 fails */
3562 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3563 "%s: kstrtou8 failed range [%d - %d]", __func__,
3564 TID_MIN_VALUE,
3565 TID_MAX_VALUE);
3566 ret = -EINVAL;
3567 goto exit;
3568 }
3569
3570 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3571 {
3572 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3573 "tid value %d is out of range"
3574 " (Min: %d Max: %d)", tid,
3575 TID_MIN_VALUE,
3576 TID_MAX_VALUE);
3577 ret = -EINVAL;
3578 goto exit;
3579 }
3580
3581 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3582 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3583
3584 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3585 {
3586 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3587 "%s: failed to get tsm stats", __func__);
3588 ret = -EFAULT;
3589 goto exit;
3590 }
3591
3592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3593 "UplinkPktQueueDly(%d)\n"
3594 "UplinkPktQueueDlyHist[0](%d)\n"
3595 "UplinkPktQueueDlyHist[1](%d)\n"
3596 "UplinkPktQueueDlyHist[2](%d)\n"
3597 "UplinkPktQueueDlyHist[3](%d)\n"
3598 "UplinkPktTxDly(%lu)\n"
3599 "UplinkPktLoss(%d)\n"
3600 "UplinkPktCount(%d)\n"
3601 "RoamingCount(%d)\n"
3602 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3603 tsmMetrics.UplinkPktQueueDlyHist[0],
3604 tsmMetrics.UplinkPktQueueDlyHist[1],
3605 tsmMetrics.UplinkPktQueueDlyHist[2],
3606 tsmMetrics.UplinkPktQueueDlyHist[3],
3607 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3608 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3609
3610 /* Output TSM stats is of the format
3611 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3612 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003613 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003614 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3615 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3616 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3617 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3618 tsmMetrics.RoamingDly);
3619
3620 if (copy_to_user(priv_data.buf, &extra, len + 1))
3621 {
3622 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3623 "%s: failed to copy data to user buffer", __func__);
3624 ret = -EFAULT;
3625 goto exit;
3626 }
3627 }
3628 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3629 {
3630 tANI_U8 *value = command;
3631 tANI_U8 *cckmIe = NULL;
3632 tANI_U8 cckmIeLen = 0;
3633 eHalStatus status = eHAL_STATUS_SUCCESS;
3634
3635 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3636 if (eHAL_STATUS_SUCCESS != status)
3637 {
3638 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3639 "%s: Failed to parse cckm ie data", __func__);
3640 ret = -EINVAL;
3641 goto exit;
3642 }
3643
3644 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3645 {
3646 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3647 "%s: CCKM Ie input length is more than max[%d]", __func__,
3648 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003649 vos_mem_free(cckmIe);
3650 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003651 ret = -EINVAL;
3652 goto exit;
3653 }
3654 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003655 vos_mem_free(cckmIe);
3656 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003657 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003658 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3659 {
3660 tANI_U8 *value = command;
3661 tCsrCcxBeaconReq ccxBcnReq;
3662 eHalStatus status = eHAL_STATUS_SUCCESS;
3663 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3664 if (eHAL_STATUS_SUCCESS != status)
3665 {
3666 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3667 "%s: Failed to parse ccx beacon req", __func__);
3668 ret = -EINVAL;
3669 goto exit;
3670 }
3671
3672 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3673 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003674#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003675 else {
3676 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3677 __func__, command);
3678 }
3679
Jeff Johnson295189b2012-06-20 16:38:30 -07003680 }
3681exit:
3682 if (command)
3683 {
3684 kfree(command);
3685 }
3686 return ret;
3687}
3688
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003689
3690
3691#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003692/**---------------------------------------------------------------------------
3693
3694 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3695
3696 This function parses the ccx beacon request passed in the format
3697 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3698 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3699 <space>Scan Mode N<space>Meas Duration N
3700 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3701 then take N.
3702 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3703 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3704 This function does not take care of removing duplicate channels from the list
3705
3706 \param - pValue Pointer to data
3707 \param - pCcxBcnReq output pointer to store parsed ie information
3708
3709 \return - 0 for success non-zero for failure
3710
3711 --------------------------------------------------------------------------*/
3712static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3713 tCsrCcxBeaconReq *pCcxBcnReq)
3714{
3715 tANI_U8 *inPtr = pValue;
3716 int tempInt = 0;
3717 int j = 0, i = 0, v = 0;
3718 char buf[32];
3719
3720 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3721 /*no argument after the command*/
3722 if (NULL == inPtr)
3723 {
3724 return -EINVAL;
3725 }
3726 /*no space after the command*/
3727 else if (SPACE_ASCII_VALUE != *inPtr)
3728 {
3729 return -EINVAL;
3730 }
3731
3732 /*removing empty spaces*/
3733 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3734
3735 /*no argument followed by spaces*/
3736 if ('\0' == *inPtr) return -EINVAL;
3737
3738 /*getting the first argument ie measurement token*/
3739 v = sscanf(inPtr, "%32s ", buf);
3740 if (1 != v) return -EINVAL;
3741
3742 v = kstrtos32(buf, 10, &tempInt);
3743 if ( v < 0) return -EINVAL;
3744
3745 pCcxBcnReq->numBcnReqIe = tempInt;
3746
3747 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3748 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3749
3750 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3751 {
3752 for (i = 0; i < 4; i++)
3753 {
3754 /*inPtr pointing to the beginning of first space after number of ie fields*/
3755 inPtr = strpbrk( inPtr, " " );
3756 /*no ie data after the number of ie fields argument*/
3757 if (NULL == inPtr) return -EINVAL;
3758
3759 /*removing empty space*/
3760 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3761
3762 /*no ie data after the number of ie fields argument and spaces*/
3763 if ( '\0' == *inPtr ) return -EINVAL;
3764
3765 v = sscanf(inPtr, "%32s ", buf);
3766 if (1 != v) return -EINVAL;
3767
3768 v = kstrtos32(buf, 10, &tempInt);
3769 if (v < 0) return -EINVAL;
3770
3771 switch (i)
3772 {
3773 case 0: /* Measurement token */
3774 if (tempInt <= 0)
3775 {
3776 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3777 "Invalid Measurement Token(%d)", tempInt);
3778 return -EINVAL;
3779 }
3780 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3781 break;
3782
3783 case 1: /* Channel number */
3784 if ((tempInt <= 0) ||
3785 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3786 {
3787 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3788 "Invalid Channel Number(%d)", tempInt);
3789 return -EINVAL;
3790 }
3791 pCcxBcnReq->bcnReq[j].channel = tempInt;
3792 break;
3793
3794 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003795 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003796 {
3797 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3798 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3799 return -EINVAL;
3800 }
3801 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3802 break;
3803
3804 case 3: /* Measurement duration */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003805 if (((tempInt <= 0) && (pCcxBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
3806 ((tempInt < 0) && (pCcxBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003807 {
3808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3809 "Invalid Measurement Duration(%d)", tempInt);
3810 return -EINVAL;
3811 }
3812 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3813 break;
3814 }
3815 }
3816 }
3817
3818 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3819 {
3820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3821 "Index(%d) Measurement Token(%lu)Channel(%lu) Scan Mode(%lu) Measurement Duration(%lu)\n",
3822 j,
3823 pCcxBcnReq->bcnReq[j].measurementToken,
3824 pCcxBcnReq->bcnReq[j].channel,
3825 pCcxBcnReq->bcnReq[j].scanMode,
3826 pCcxBcnReq->bcnReq[j].measurementDuration);
3827 }
3828
3829 return VOS_STATUS_SUCCESS;
3830}
3831
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003832static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3833{
3834 struct statsContext *pStatsContext = NULL;
3835 hdd_adapter_t *pAdapter = NULL;
3836
3837 if (NULL == pContext)
3838 {
3839 hddLog(VOS_TRACE_LEVEL_ERROR,
3840 "%s: Bad param, pContext [%p]",
3841 __func__, pContext);
3842 return;
3843 }
3844
3845 /* there is a race condition that exists between this callback function
3846 and the caller since the caller could time out either before or
3847 while this code is executing. we'll assume the timeout hasn't
3848 occurred, but we'll verify that right before we save our work */
3849
3850 pStatsContext = pContext;
3851 pAdapter = pStatsContext->pAdapter;
3852 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3853 {
3854 /* the caller presumably timed out so there is nothing we can do */
3855 hddLog(VOS_TRACE_LEVEL_WARN,
3856 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3857 __func__, pAdapter, pStatsContext->magic);
3858 return;
3859 }
3860
3861 /* the race is on. caller could have timed out immediately after
3862 we verified the magic, but if so, caller will wait a short time
3863 for us to copy over the tsm stats */
3864 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3865 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3866 tsmMetrics.UplinkPktQueueDlyHist,
3867 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3868 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3869 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3870 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3871 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3872 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3873 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3874
3875 /* and notify the caller */
3876 complete(&pStatsContext->completion);
3877}
3878
3879
3880
3881static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3882 tAniTrafStrmMetrics* pTsmMetrics)
3883{
3884 hdd_station_ctx_t *pHddStaCtx = NULL;
3885 eHalStatus hstatus;
3886 long lrc;
3887 struct statsContext context;
3888 hdd_context_t *pHddCtx = NULL;
3889
3890 if (NULL == pAdapter)
3891 {
3892 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3893 return VOS_STATUS_E_FAULT;
3894 }
3895
3896 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3897 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3898
3899 /* we are connected prepare our callback context */
3900 init_completion(&context.completion);
3901 context.pAdapter = pAdapter;
3902 context.magic = STATS_CONTEXT_MAGIC;
3903
3904 /* query tsm stats */
3905 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3906 pHddStaCtx->conn_info.staId[ 0 ],
3907 pHddStaCtx->conn_info.bssId,
3908 &context, pHddCtx->pvosContext, tid);
3909
3910 if (eHAL_STATUS_SUCCESS != hstatus)
3911 {
3912 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics", __func__);
3913 return hstatus;
3914 }
3915 else
3916 {
3917 /* request was sent -- wait for the response */
3918 lrc = wait_for_completion_interruptible_timeout(&context.completion,
3919 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
3920 /* either we have a response or we timed out
3921 either way, first invalidate our magic */
3922 context.magic = 0;
3923 if (lrc <= 0)
3924 {
3925 hddLog(VOS_TRACE_LEVEL_ERROR,
3926 "%s: SME %s while retrieving statistics",
3927 __func__, (0 == lrc) ? "timeout" : "interrupt");
3928 /* there is a race condition such that the callback
3929 function could be executing at the same time we are. of
3930 primary concern is if the callback function had already
3931 verified the "magic" but hasn't yet set the completion
3932 variable. Since the completion variable is on our
3933 stack, we'll delay just a bit to make sure the data is
3934 still valid if that is the case */
3935 msleep(50);
3936 return (VOS_STATUS_E_TIMEOUT);
3937 }
3938 }
3939 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
3940 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
3941 pAdapter->tsmStats.UplinkPktQueueDlyHist,
3942 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3943 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3944 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
3945 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
3946 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
3947 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
3948 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
3949
3950 return VOS_STATUS_SUCCESS;
3951}
3952#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
3953
Srinivas Girigowdade697412013-02-14 16:31:48 -08003954#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
3955void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
3956{
3957 eCsrBand band = -1;
3958 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
3959 switch (band)
3960 {
3961 case eCSR_BAND_ALL:
3962 *pBand = WLAN_HDD_UI_BAND_AUTO;
3963 break;
3964
3965 case eCSR_BAND_24:
3966 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
3967 break;
3968
3969 case eCSR_BAND_5G:
3970 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
3971 break;
3972
3973 default:
3974 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
3975 *pBand = -1;
3976 break;
3977 }
3978}
3979
3980/**---------------------------------------------------------------------------
3981
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003982 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
3983
3984 This function parses the send action frame data passed in the format
3985 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
3986
Srinivas Girigowda56076852013-08-20 14:00:50 -07003987 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003988 \param - pTargetApBssid Pointer to target Ap bssid
3989 \param - pChannel Pointer to the Target AP channel
3990 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
3991 \param - pBuf Pointer to data
3992 \param - pBufLen Pointer to data length
3993
3994 \return - 0 for success non-zero for failure
3995
3996 --------------------------------------------------------------------------*/
3997VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
3998 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
3999{
4000 tANI_U8 *inPtr = pValue;
4001 tANI_U8 *dataEnd;
4002 int tempInt;
4003 int j = 0;
4004 int i = 0;
4005 int v = 0;
4006 tANI_U8 tempBuf[32];
4007 tANI_U8 tempByte = 0;
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004008 /* 12 hexa decimal digits and 5 ':' */
4009 tANI_U8 macAddress[17];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004010
4011 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4012 /*no argument after the command*/
4013 if (NULL == inPtr)
4014 {
4015 return -EINVAL;
4016 }
4017
4018 /*no space after the command*/
4019 else if (SPACE_ASCII_VALUE != *inPtr)
4020 {
4021 return -EINVAL;
4022 }
4023
4024 /*removing empty spaces*/
4025 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4026
4027 /*no argument followed by spaces*/
4028 if ('\0' == *inPtr)
4029 {
4030 return -EINVAL;
4031 }
4032
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004033 v = sscanf(inPtr, "%17s", macAddress);
4034 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004035 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004036 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4037 "Invalid MAC address or All hex inputs are not read (%d)", v);
4038 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004039 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004040
4041 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4042 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4043 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4044 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4045 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4046 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004047
4048 /* point to the next argument */
4049 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4050 /*no argument after the command*/
4051 if (NULL == inPtr) return -EINVAL;
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
4062 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004063 v = sscanf(inPtr, "%32s ", tempBuf);
4064 if (1 != v) return -EINVAL;
4065
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004066 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304067 if ( v < 0 || tempInt <= 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
4068 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004069
4070 *pChannel = tempInt;
4071
4072 /* point to the next argument */
4073 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4074 /*no argument after the command*/
4075 if (NULL == inPtr) return -EINVAL;
4076 /*removing empty spaces*/
4077 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4078
4079 /*no argument followed by spaces*/
4080 if ('\0' == *inPtr)
4081 {
4082 return -EINVAL;
4083 }
4084
4085 /*getting the next argument ie the dwell time */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004086 v = sscanf(inPtr, "%32s ", tempBuf);
4087 if (1 != v) return -EINVAL;
4088
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004089 v = kstrtos32(tempBuf, 10, &tempInt);
Kiet Lambe150c22013-11-21 16:30:32 +05304090 if ( v < 0 || tempInt <= 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004091
4092 *pDwellTime = tempInt;
4093
4094 /* point to the next argument */
4095 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4096 /*no argument after the command*/
4097 if (NULL == inPtr) return -EINVAL;
4098 /*removing empty spaces*/
4099 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4100
4101 /*no argument followed by spaces*/
4102 if ('\0' == *inPtr)
4103 {
4104 return -EINVAL;
4105 }
4106
4107 /* find the length of data */
4108 dataEnd = inPtr;
4109 while(('\0' != *dataEnd) )
4110 {
4111 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004112 }
Kiet Lambe150c22013-11-21 16:30:32 +05304113 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004114 if ( *pBufLen <= 0) return -EINVAL;
4115
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004116 /* Allocate the number of bytes based on the number of input characters
4117 whether it is even or odd.
4118 if the number of input characters are even, then we need N/2 byte.
4119 if the number of input characters are odd, then we need do (N+1)/2 to
4120 compensate rounding off.
4121 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4122 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4123 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004124 if (NULL == *pBuf)
4125 {
4126 hddLog(VOS_TRACE_LEVEL_FATAL,
4127 "%s: vos_mem_alloc failed ", __func__);
4128 return -EINVAL;
4129 }
4130
4131 /* the buffer received from the upper layer is character buffer,
4132 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4133 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4134 and f0 in 3rd location */
4135 for (i = 0, j = 0; j < *pBufLen; j += 2)
4136 {
Kiet Lambe150c22013-11-21 16:30:32 +05304137 if( j+1 == *pBufLen)
4138 {
4139 tempByte = hdd_parse_hex(inPtr[j]);
4140 }
4141 else
4142 {
4143 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4144 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004145 (*pBuf)[i++] = tempByte;
4146 }
4147 *pBufLen = i;
4148 return VOS_STATUS_SUCCESS;
4149}
4150
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004151/**---------------------------------------------------------------------------
4152
Srinivas Girigowdade697412013-02-14 16:31:48 -08004153 \brief hdd_parse_channellist() - HDD Parse channel list
4154
4155 This function parses the channel list passed in the format
4156 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004157 if the Number of channels (N) does not match with the actual number of channels passed
4158 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4159 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4160 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4161 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004162
4163 \param - pValue Pointer to input channel list
4164 \param - ChannelList Pointer to local output array to record channel list
4165 \param - pNumChannels Pointer to number of roam scan channels
4166
4167 \return - 0 for success non-zero for failure
4168
4169 --------------------------------------------------------------------------*/
4170VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4171{
4172 tANI_U8 *inPtr = pValue;
4173 int tempInt;
4174 int j = 0;
4175 int v = 0;
4176 char buf[32];
4177
4178 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4179 /*no argument after the command*/
4180 if (NULL == inPtr)
4181 {
4182 return -EINVAL;
4183 }
4184
4185 /*no space after the command*/
4186 else if (SPACE_ASCII_VALUE != *inPtr)
4187 {
4188 return -EINVAL;
4189 }
4190
4191 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004192 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004193
4194 /*no argument followed by spaces*/
4195 if ('\0' == *inPtr)
4196 {
4197 return -EINVAL;
4198 }
4199
4200 /*getting the first argument ie the number of channels*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004201 v = sscanf(inPtr, "%32s ", buf);
4202 if (1 != v) return -EINVAL;
4203
Srinivas Girigowdade697412013-02-14 16:31:48 -08004204 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004205 if ((v < 0) ||
4206 (tempInt <= 0) ||
4207 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4208 {
4209 return -EINVAL;
4210 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004211
4212 *pNumChannels = tempInt;
4213
4214 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4215 "Number of channels are: %d", *pNumChannels);
4216
4217 for (j = 0; j < (*pNumChannels); j++)
4218 {
4219 /*inPtr pointing to the beginning of first space after number of channels*/
4220 inPtr = strpbrk( inPtr, " " );
4221 /*no channel list after the number of channels argument*/
4222 if (NULL == inPtr)
4223 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004224 if (0 != j)
4225 {
4226 *pNumChannels = j;
4227 return VOS_STATUS_SUCCESS;
4228 }
4229 else
4230 {
4231 return -EINVAL;
4232 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004233 }
4234
4235 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004236 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004237
4238 /*no channel list after the number of channels argument and spaces*/
4239 if ( '\0' == *inPtr )
4240 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004241 if (0 != j)
4242 {
4243 *pNumChannels = j;
4244 return VOS_STATUS_SUCCESS;
4245 }
4246 else
4247 {
4248 return -EINVAL;
4249 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004250 }
4251
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004252 v = sscanf(inPtr, "%32s ", buf);
4253 if (1 != v) return -EINVAL;
4254
Srinivas Girigowdade697412013-02-14 16:31:48 -08004255 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004256 if ((v < 0) ||
4257 (tempInt <= 0) ||
4258 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4259 {
4260 return -EINVAL;
4261 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004262 pChannelList[j] = tempInt;
4263
4264 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4265 "Channel %d added to preferred channel list",
4266 pChannelList[j] );
4267 }
4268
Srinivas Girigowdade697412013-02-14 16:31:48 -08004269 return VOS_STATUS_SUCCESS;
4270}
4271
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004272
4273/**---------------------------------------------------------------------------
4274
4275 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4276
4277 This function parses the reasoc command data passed in the format
4278 REASSOC<space><bssid><space><channel>
4279
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004280 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004281 \param - pTargetApBssid Pointer to target Ap bssid
4282 \param - pChannel Pointer to the Target AP channel
4283
4284 \return - 0 for success non-zero for failure
4285
4286 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004287VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4288 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004289{
4290 tANI_U8 *inPtr = pValue;
4291 int tempInt;
4292 int v = 0;
4293 tANI_U8 tempBuf[32];
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004294 /* 12 hexa decimal digits and 5 ':' */
4295 tANI_U8 macAddress[17];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004296
4297 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4298 /*no argument after the command*/
4299 if (NULL == inPtr)
4300 {
4301 return -EINVAL;
4302 }
4303
4304 /*no space after the command*/
4305 else if (SPACE_ASCII_VALUE != *inPtr)
4306 {
4307 return -EINVAL;
4308 }
4309
4310 /*removing empty spaces*/
4311 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4312
4313 /*no argument followed by spaces*/
4314 if ('\0' == *inPtr)
4315 {
4316 return -EINVAL;
4317 }
4318
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004319 v = sscanf(inPtr, "%17s", macAddress);
4320 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004321 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004322 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4323 "Invalid MAC address or All hex inputs are not read (%d)", v);
4324 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004325 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004326
4327 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4328 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4329 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4330 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4331 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4332 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004333
4334 /* point to the next argument */
4335 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4336 /*no argument after the command*/
4337 if (NULL == inPtr) return -EINVAL;
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
4348 /*getting the next argument ie the channel number */
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004349 v = sscanf(inPtr, "%32s ", tempBuf);
4350 if (1 != v) return -EINVAL;
4351
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004352 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004353 if ((v < 0) ||
4354 (tempInt <= 0) ||
4355 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4356 {
4357 return -EINVAL;
4358 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004359
4360 *pChannel = tempInt;
4361 return VOS_STATUS_SUCCESS;
4362}
4363
4364#endif
4365
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004366#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4367/**---------------------------------------------------------------------------
4368
4369 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4370
4371 This function parses the SETCCKM IE command
4372 SETCCKMIE<space><ie data>
4373
4374 \param - pValue Pointer to input data
4375 \param - pCckmIe Pointer to output cckm Ie
4376 \param - pCckmIeLen Pointer to output cckm ie length
4377
4378 \return - 0 for success non-zero for failure
4379
4380 --------------------------------------------------------------------------*/
4381VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4382 tANI_U8 *pCckmIeLen)
4383{
4384 tANI_U8 *inPtr = pValue;
4385 tANI_U8 *dataEnd;
4386 int j = 0;
4387 int i = 0;
4388 tANI_U8 tempByte = 0;
4389
4390 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4391 /*no argument after the command*/
4392 if (NULL == inPtr)
4393 {
4394 return -EINVAL;
4395 }
4396
4397 /*no space after the command*/
4398 else if (SPACE_ASCII_VALUE != *inPtr)
4399 {
4400 return -EINVAL;
4401 }
4402
4403 /*removing empty spaces*/
4404 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4405
4406 /*no argument followed by spaces*/
4407 if ('\0' == *inPtr)
4408 {
4409 return -EINVAL;
4410 }
4411
4412 /* find the length of data */
4413 dataEnd = inPtr;
4414 while(('\0' != *dataEnd) )
4415 {
4416 dataEnd++;
4417 ++(*pCckmIeLen);
4418 }
4419 if ( *pCckmIeLen <= 0) return -EINVAL;
4420
4421 /* Allocate the number of bytes based on the number of input characters
4422 whether it is even or odd.
4423 if the number of input characters are even, then we need N/2 byte.
4424 if the number of input characters are odd, then we need do (N+1)/2 to
4425 compensate rounding off.
4426 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4427 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4428 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4429 if (NULL == *pCckmIe)
4430 {
4431 hddLog(VOS_TRACE_LEVEL_FATAL,
4432 "%s: vos_mem_alloc failed ", __func__);
4433 return -EINVAL;
4434 }
4435 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4436 /* the buffer received from the upper layer is character buffer,
4437 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4438 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4439 and f0 in 3rd location */
4440 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4441 {
4442 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4443 (*pCckmIe)[i++] = tempByte;
4444 }
4445 *pCckmIeLen = i;
4446
4447 return VOS_STATUS_SUCCESS;
4448}
4449#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4450
Jeff Johnson295189b2012-06-20 16:38:30 -07004451/**---------------------------------------------------------------------------
4452
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004453 \brief hdd_is_valid_mac_address() - Validate MAC address
4454
4455 This function validates whether the given MAC address is valid or not
4456 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4457 where X is the hexa decimal digit character and separated by ':'
4458 This algorithm works even if MAC address is not separated by ':'
4459
4460 This code checks given input string mac contains exactly 12 hexadecimal digits.
4461 and a separator colon : appears in the input string only after
4462 an even number of hex digits.
4463
4464 \param - pMacAddr pointer to the input MAC address
4465 \return - 1 for valid and 0 for invalid
4466
4467 --------------------------------------------------------------------------*/
4468
4469v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4470{
4471 int xdigit = 0;
4472 int separator = 0;
4473 while (*pMacAddr)
4474 {
4475 if (isxdigit(*pMacAddr))
4476 {
4477 xdigit++;
4478 }
4479 else if (':' == *pMacAddr)
4480 {
4481 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4482 break;
4483
4484 ++separator;
4485 }
4486 else
4487 {
4488 separator = -1;
4489 /* Invalid MAC found */
4490 return 0;
4491 }
4492 ++pMacAddr;
4493 }
4494 return (xdigit == 12 && (separator == 5 || separator == 0));
4495}
4496
4497/**---------------------------------------------------------------------------
4498
Jeff Johnson295189b2012-06-20 16:38:30 -07004499 \brief hdd_open() - HDD Open function
4500
4501 This is called in response to ifconfig up
4502
4503 \param - dev Pointer to net_device structure
4504
4505 \return - 0 for success non-zero for failure
4506
4507 --------------------------------------------------------------------------*/
4508int hdd_open (struct net_device *dev)
4509{
4510 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4511 hdd_context_t *pHddCtx;
4512 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4513 VOS_STATUS status;
4514 v_BOOL_t in_standby = TRUE;
4515
4516 if (NULL == pAdapter)
4517 {
4518 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004519 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004520 return -ENODEV;
4521 }
4522
4523 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4524 if (NULL == pHddCtx)
4525 {
4526 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004527 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004528 return -ENODEV;
4529 }
4530
4531 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4532 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4533 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004534 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4535 {
4536 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304537 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004538 in_standby = FALSE;
4539 break;
4540 }
4541 else
4542 {
4543 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4544 pAdapterNode = pNext;
4545 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004546 }
4547
4548 if (TRUE == in_standby)
4549 {
4550 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4551 {
4552 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4553 "wlan out of power save", __func__);
4554 return -EINVAL;
4555 }
4556 }
4557
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004558 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004559 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4560 {
4561 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004562 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004563 /* Enable TX queues only when we are connected */
4564 netif_tx_start_all_queues(dev);
4565 }
4566
4567 return 0;
4568}
4569
4570int hdd_mon_open (struct net_device *dev)
4571{
4572 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4573
4574 if(pAdapter == NULL) {
4575 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004576 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004577 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004578 }
4579
4580 netif_start_queue(dev);
4581
4582 return 0;
4583}
4584/**---------------------------------------------------------------------------
4585
4586 \brief hdd_stop() - HDD stop function
4587
4588 This is called in response to ifconfig down
4589
4590 \param - dev Pointer to net_device structure
4591
4592 \return - 0 for success non-zero for failure
4593
4594 --------------------------------------------------------------------------*/
4595
4596int hdd_stop (struct net_device *dev)
4597{
4598 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4599 hdd_context_t *pHddCtx;
4600 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4601 VOS_STATUS status;
4602 v_BOOL_t enter_standby = TRUE;
4603
4604 ENTER();
4605
4606 if (NULL == pAdapter)
4607 {
4608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004609 "%s: HDD adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004610 return -ENODEV;
4611 }
4612
4613 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4614 if (NULL == pHddCtx)
4615 {
4616 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004617 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004618 return -ENODEV;
4619 }
4620
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004621 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004622 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4623 netif_tx_disable(pAdapter->dev);
4624 netif_carrier_off(pAdapter->dev);
4625
4626
4627 /* SoftAP ifaces should never go in power save mode
4628 making sure same here. */
4629 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4630 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004631 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004632 )
4633 {
4634 /* SoftAP mode, so return from here */
4635 EXIT();
4636 return 0;
4637 }
4638
4639 /* Find if any iface is up then
4640 if any iface is up then can't put device to sleep/ power save mode. */
4641 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4642 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4643 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004644 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4645 {
4646 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304647 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004648 enter_standby = FALSE;
4649 break;
4650 }
4651 else
4652 {
4653 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4654 pAdapterNode = pNext;
4655 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004656 }
4657
4658 if (TRUE == enter_standby)
4659 {
4660 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4661 "entering standby", __func__);
4662 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4663 {
4664 /*log and return success*/
4665 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4666 "wlan in power save", __func__);
4667 }
4668 }
4669
4670 EXIT();
4671 return 0;
4672}
4673
4674/**---------------------------------------------------------------------------
4675
4676 \brief hdd_uninit() - HDD uninit function
4677
4678 This is called during the netdev unregister to uninitialize all data
4679associated with the device
4680
4681 \param - dev Pointer to net_device structure
4682
4683 \return - void
4684
4685 --------------------------------------------------------------------------*/
4686static void hdd_uninit (struct net_device *dev)
4687{
4688 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4689
4690 ENTER();
4691
4692 do
4693 {
4694 if (NULL == pAdapter)
4695 {
4696 hddLog(VOS_TRACE_LEVEL_FATAL,
4697 "%s: NULL pAdapter", __func__);
4698 break;
4699 }
4700
4701 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4702 {
4703 hddLog(VOS_TRACE_LEVEL_FATAL,
4704 "%s: Invalid magic", __func__);
4705 break;
4706 }
4707
4708 if (NULL == pAdapter->pHddCtx)
4709 {
4710 hddLog(VOS_TRACE_LEVEL_FATAL,
4711 "%s: NULL pHddCtx", __func__);
4712 break;
4713 }
4714
4715 if (dev != pAdapter->dev)
4716 {
4717 hddLog(VOS_TRACE_LEVEL_FATAL,
4718 "%s: Invalid device reference", __func__);
4719 /* we haven't validated all cases so let this go for now */
4720 }
4721
4722 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4723
4724 /* after uninit our adapter structure will no longer be valid */
4725 pAdapter->dev = NULL;
4726 pAdapter->magic = 0;
4727 } while (0);
4728
4729 EXIT();
4730}
4731
4732/**---------------------------------------------------------------------------
4733
4734 \brief hdd_release_firmware() -
4735
4736 This function calls the release firmware API to free the firmware buffer.
4737
4738 \param - pFileName Pointer to the File Name.
4739 pCtx - Pointer to the adapter .
4740
4741
4742 \return - 0 for success, non zero for failure
4743
4744 --------------------------------------------------------------------------*/
4745
4746VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4747{
4748 VOS_STATUS status = VOS_STATUS_SUCCESS;
4749 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4750 ENTER();
4751
4752
4753 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4754
4755 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4756
4757 if(pHddCtx->fw) {
4758 release_firmware(pHddCtx->fw);
4759 pHddCtx->fw = NULL;
4760 }
4761 else
4762 status = VOS_STATUS_E_FAILURE;
4763 }
4764 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4765 if(pHddCtx->nv) {
4766 release_firmware(pHddCtx->nv);
4767 pHddCtx->nv = NULL;
4768 }
4769 else
4770 status = VOS_STATUS_E_FAILURE;
4771
4772 }
4773
4774 EXIT();
4775 return status;
4776}
4777
4778/**---------------------------------------------------------------------------
4779
4780 \brief hdd_request_firmware() -
4781
4782 This function reads the firmware file using the request firmware
4783 API and returns the the firmware data and the firmware file size.
4784
4785 \param - pfileName - Pointer to the file name.
4786 - pCtx - Pointer to the adapter .
4787 - ppfw_data - Pointer to the pointer of the firmware data.
4788 - pSize - Pointer to the file size.
4789
4790 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4791
4792 --------------------------------------------------------------------------*/
4793
4794
4795VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4796{
4797 int status;
4798 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4799 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4800 ENTER();
4801
4802 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4803
4804 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4805
4806 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4807 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4808 __func__, pfileName);
4809 retval = VOS_STATUS_E_FAILURE;
4810 }
4811
4812 else {
4813 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4814 *pSize = pHddCtx->fw->size;
4815 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4816 __func__, *pSize);
4817 }
4818 }
4819 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4820
4821 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4822
4823 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4824 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4825 __func__, pfileName);
4826 retval = VOS_STATUS_E_FAILURE;
4827 }
4828
4829 else {
4830 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4831 *pSize = pHddCtx->nv->size;
4832 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4833 __func__, *pSize);
4834 }
4835 }
4836
4837 EXIT();
4838 return retval;
4839}
4840/**---------------------------------------------------------------------------
4841 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4842
4843 This is the function invoked by SME to inform the result of a full power
4844 request issued by HDD
4845
4846 \param - callbackcontext - Pointer to cookie
4847 status - result of request
4848
4849 \return - None
4850
4851--------------------------------------------------------------------------*/
4852void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4853{
4854 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4855
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004856 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004857 if(&pHddCtx->full_pwr_comp_var)
4858 {
4859 complete(&pHddCtx->full_pwr_comp_var);
4860 }
4861}
4862
4863/**---------------------------------------------------------------------------
4864
4865 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4866
4867 This is the function invoked by SME to inform the result of BMPS
4868 request issued by HDD
4869
4870 \param - callbackcontext - Pointer to cookie
4871 status - result of request
4872
4873 \return - None
4874
4875--------------------------------------------------------------------------*/
4876void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4877{
4878
4879 struct completion *completion_var = (struct completion*) callbackContext;
4880
Arif Hussain6d2a3322013-11-17 19:50:10 -08004881 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004882 if(completion_var != NULL)
4883 {
4884 complete(completion_var);
4885 }
4886}
4887
4888/**---------------------------------------------------------------------------
4889
4890 \brief hdd_get_cfg_file_size() -
4891
4892 This function reads the configuration file using the request firmware
4893 API and returns the configuration file size.
4894
4895 \param - pCtx - Pointer to the adapter .
4896 - pFileName - Pointer to the file name.
4897 - pBufSize - Pointer to the buffer size.
4898
4899 \return - 0 for success, non zero for failure
4900
4901 --------------------------------------------------------------------------*/
4902
4903VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4904{
4905 int status;
4906 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4907
4908 ENTER();
4909
4910 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4911
4912 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4913 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4914 status = VOS_STATUS_E_FAILURE;
4915 }
4916 else {
4917 *pBufSize = pHddCtx->fw->size;
4918 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
4919 release_firmware(pHddCtx->fw);
4920 pHddCtx->fw = NULL;
4921 }
4922
4923 EXIT();
4924 return VOS_STATUS_SUCCESS;
4925}
4926
4927/**---------------------------------------------------------------------------
4928
4929 \brief hdd_read_cfg_file() -
4930
4931 This function reads the configuration file using the request firmware
4932 API and returns the cfg data and the buffer size of the configuration file.
4933
4934 \param - pCtx - Pointer to the adapter .
4935 - pFileName - Pointer to the file name.
4936 - pBuffer - Pointer to the data buffer.
4937 - pBufSize - Pointer to the buffer size.
4938
4939 \return - 0 for success, non zero for failure
4940
4941 --------------------------------------------------------------------------*/
4942
4943VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
4944 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
4945{
4946 int status;
4947 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4948
4949 ENTER();
4950
4951 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
4952
4953 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4954 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
4955 return VOS_STATUS_E_FAILURE;
4956 }
4957 else {
4958 if(*pBufSize != pHddCtx->fw->size) {
4959 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
4960 "file size", __func__);
4961 release_firmware(pHddCtx->fw);
4962 pHddCtx->fw = NULL;
4963 return VOS_STATUS_E_FAILURE;
4964 }
4965 else {
4966 if(pBuffer) {
4967 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
4968 }
4969 release_firmware(pHddCtx->fw);
4970 pHddCtx->fw = NULL;
4971 }
4972 }
4973
4974 EXIT();
4975
4976 return VOS_STATUS_SUCCESS;
4977}
4978
4979/**---------------------------------------------------------------------------
4980
Jeff Johnson295189b2012-06-20 16:38:30 -07004981 \brief hdd_set_mac_address() -
4982
4983 This function sets the user specified mac address using
4984 the command ifconfig wlanX hw ether <mac adress>.
4985
4986 \param - dev - Pointer to the net device.
4987 - addr - Pointer to the sockaddr.
4988 \return - 0 for success, non zero for failure
4989
4990 --------------------------------------------------------------------------*/
4991
4992static int hdd_set_mac_address(struct net_device *dev, void *addr)
4993{
4994 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4995 struct sockaddr *psta_mac_addr = addr;
4996 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
4997
4998 ENTER();
4999
5000 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5001
5002#ifdef HDD_SESSIONIZE
5003 // set the MAC address though the STA ID CFG.
5004 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5005 (v_U8_t *)&pAdapter->macAddressCurrent,
5006 sizeof( pAdapter->macAddressCurrent ),
5007 hdd_set_mac_addr_cb, VOS_FALSE );
5008#endif
5009
5010 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5011
5012 EXIT();
5013 return halStatus;
5014}
5015
5016tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5017{
5018 int i;
5019 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5020 {
5021 if( 0 == (pHddCtx->cfg_ini->intfAddrMask >> i))
5022 break;
5023 }
5024
5025 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5026 return NULL;
5027
5028 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5029 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5030}
5031
5032void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5033{
5034 int i;
5035 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5036 {
5037 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5038 {
5039 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5040 break;
5041 }
5042 }
5043 return;
5044}
5045
5046#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5047 static struct net_device_ops wlan_drv_ops = {
5048 .ndo_open = hdd_open,
5049 .ndo_stop = hdd_stop,
5050 .ndo_uninit = hdd_uninit,
5051 .ndo_start_xmit = hdd_hard_start_xmit,
5052 .ndo_tx_timeout = hdd_tx_timeout,
5053 .ndo_get_stats = hdd_stats,
5054 .ndo_do_ioctl = hdd_ioctl,
5055 .ndo_set_mac_address = hdd_set_mac_address,
5056 .ndo_select_queue = hdd_select_queue,
5057#ifdef WLAN_FEATURE_PACKET_FILTERING
5058#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5059 .ndo_set_rx_mode = hdd_set_multicast_list,
5060#else
5061 .ndo_set_multicast_list = hdd_set_multicast_list,
5062#endif //LINUX_VERSION_CODE
5063#endif
5064 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005065 static struct net_device_ops wlan_mon_drv_ops = {
5066 .ndo_open = hdd_mon_open,
5067 .ndo_stop = hdd_stop,
5068 .ndo_uninit = hdd_uninit,
5069 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5070 .ndo_tx_timeout = hdd_tx_timeout,
5071 .ndo_get_stats = hdd_stats,
5072 .ndo_do_ioctl = hdd_ioctl,
5073 .ndo_set_mac_address = hdd_set_mac_address,
5074 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005075
5076#endif
5077
5078void hdd_set_station_ops( struct net_device *pWlanDev )
5079{
5080#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005081 pWlanDev->netdev_ops = &wlan_drv_ops;
5082#else
5083 pWlanDev->open = hdd_open;
5084 pWlanDev->stop = hdd_stop;
5085 pWlanDev->uninit = hdd_uninit;
5086 pWlanDev->hard_start_xmit = NULL;
5087 pWlanDev->tx_timeout = hdd_tx_timeout;
5088 pWlanDev->get_stats = hdd_stats;
5089 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005090 pWlanDev->set_mac_address = hdd_set_mac_address;
5091#endif
5092}
5093
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005094static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005095{
5096 struct net_device *pWlanDev = NULL;
5097 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005098 /*
5099 * cfg80211 initialization and registration....
5100 */
5101 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5102
Jeff Johnson295189b2012-06-20 16:38:30 -07005103 if(pWlanDev != NULL)
5104 {
5105
5106 //Save the pointer to the net_device in the HDD adapter
5107 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5108
Jeff Johnson295189b2012-06-20 16:38:30 -07005109 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5110
5111 pAdapter->dev = pWlanDev;
5112 pAdapter->pHddCtx = pHddCtx;
5113 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5114
5115 init_completion(&pAdapter->session_open_comp_var);
5116 init_completion(&pAdapter->session_close_comp_var);
5117 init_completion(&pAdapter->disconnect_comp_var);
5118 init_completion(&pAdapter->linkup_event_var);
5119 init_completion(&pAdapter->cancel_rem_on_chan_var);
5120 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005121#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5122 init_completion(&pAdapter->offchannel_tx_event);
5123#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005124 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005125#ifdef FEATURE_WLAN_TDLS
5126 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005127 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005128 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305129 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005130#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005131 init_completion(&pHddCtx->mc_sus_event_var);
5132 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305133 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005134 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005135 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005136
Rajeev79dbe4c2013-10-05 11:03:42 +05305137#ifdef FEATURE_WLAN_BATCH_SCAN
5138 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5139 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5140 pAdapter->pBatchScanRsp = NULL;
5141 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005142 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Rajeev Kumarb20d8c82013-11-18 20:04:20 -08005143 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305144 mutex_init(&pAdapter->hdd_batch_scan_lock);
5145#endif
5146
Jeff Johnson295189b2012-06-20 16:38:30 -07005147 pAdapter->isLinkUpSvcNeeded = FALSE;
5148 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5149 //Init the net_device structure
5150 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5151
5152 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5153 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5154 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5155 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5156
5157 hdd_set_station_ops( pAdapter->dev );
5158
5159 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005160 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5161 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5162 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005163 /* set pWlanDev's parent to underlying device */
5164 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5165 }
5166
5167 return pAdapter;
5168}
5169
5170VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5171{
5172 struct net_device *pWlanDev = pAdapter->dev;
5173 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5174 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5175 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5176
5177 if( rtnl_lock_held )
5178 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005179 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005180 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5181 {
5182 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5183 return VOS_STATUS_E_FAILURE;
5184 }
5185 }
5186 if (register_netdevice(pWlanDev))
5187 {
5188 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5189 return VOS_STATUS_E_FAILURE;
5190 }
5191 }
5192 else
5193 {
5194 if(register_netdev(pWlanDev))
5195 {
5196 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5197 return VOS_STATUS_E_FAILURE;
5198 }
5199 }
5200 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5201
5202 return VOS_STATUS_SUCCESS;
5203}
5204
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005205static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005206{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005207 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005208
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005209 if (NULL == pAdapter)
5210 {
5211 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5212 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005213 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005214
5215 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5216 {
5217 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5218 return eHAL_STATUS_NOT_INITIALIZED;
5219 }
5220
5221 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5222
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005223#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005224 /* need to make sure all of our scheduled work has completed.
5225 * This callback is called from MC thread context, so it is safe to
5226 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005227 *
5228 * Even though this is called from MC thread context, if there is a faulty
5229 * work item in the system, that can hang this call forever. So flushing
5230 * this global work queue is not safe; and now we make sure that
5231 * individual work queues are stopped correctly. But the cancel work queue
5232 * is a GPL only API, so the proprietary version of the driver would still
5233 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005234 */
5235 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005236#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005237
5238 /* We can be blocked while waiting for scheduled work to be
5239 * flushed, and the adapter structure can potentially be freed, in
5240 * which case the magic will have been reset. So make sure the
5241 * magic is still good, and hence the adapter structure is still
5242 * valid, before signaling completion */
5243 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5244 {
5245 complete(&pAdapter->session_close_comp_var);
5246 }
5247
Jeff Johnson295189b2012-06-20 16:38:30 -07005248 return eHAL_STATUS_SUCCESS;
5249}
5250
5251VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5252{
5253 struct net_device *pWlanDev = pAdapter->dev;
5254 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5255 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5256 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5257 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5258 int rc = 0;
5259
5260 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005261 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005262 //Open a SME session for future operation
5263 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005264 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005265 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5266 {
5267 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005268 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005269 halStatus, halStatus );
5270 status = VOS_STATUS_E_FAILURE;
5271 goto error_sme_open;
5272 }
5273
5274 //Block on a completion variable. Can't wait forever though.
5275 rc = wait_for_completion_interruptible_timeout(
5276 &pAdapter->session_open_comp_var,
5277 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
5278 if (!rc)
5279 {
5280 hddLog(VOS_TRACE_LEVEL_FATAL,
5281 "Session is not opened within timeout period code %08d", rc );
5282 status = VOS_STATUS_E_FAILURE;
5283 goto error_sme_open;
5284 }
5285
5286 // Register wireless extensions
5287 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5288 {
5289 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005290 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005291 halStatus, halStatus );
5292 status = VOS_STATUS_E_FAILURE;
5293 goto error_register_wext;
5294 }
5295 //Safe to register the hard_start_xmit function again
5296#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5297 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5298#else
5299 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5300#endif
5301
5302 //Set the Connection State to Not Connected
5303 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5304
5305 //Set the default operation channel
5306 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5307
5308 /* Make the default Auth Type as OPEN*/
5309 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5310
5311 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5312 {
5313 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005314 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005315 status, status );
5316 goto error_init_txrx;
5317 }
5318
5319 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5320
5321 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5322 {
5323 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005324 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005325 status, status );
5326 goto error_wmm_init;
5327 }
5328
5329 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5330
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005331#ifdef FEATURE_WLAN_TDLS
5332 if(0 != wlan_hdd_tdls_init(pAdapter))
5333 {
5334 status = VOS_STATUS_E_FAILURE;
5335 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5336 goto error_tdls_init;
5337 }
5338 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5339#endif
5340
Jeff Johnson295189b2012-06-20 16:38:30 -07005341 return VOS_STATUS_SUCCESS;
5342
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005343#ifdef FEATURE_WLAN_TDLS
5344error_tdls_init:
5345 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5346 hdd_wmm_adapter_close(pAdapter);
5347#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005348error_wmm_init:
5349 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5350 hdd_deinit_tx_rx(pAdapter);
5351error_init_txrx:
5352 hdd_UnregisterWext(pWlanDev);
5353error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005354 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005355 {
5356 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005357 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005358 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005359 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005360 {
5361 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005362 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005363 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005364 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
Jeff Johnson295189b2012-06-20 16:38:30 -07005365 }
5366}
5367error_sme_open:
5368 return status;
5369}
5370
Jeff Johnson295189b2012-06-20 16:38:30 -07005371void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5372{
5373 hdd_cfg80211_state_t *cfgState;
5374
5375 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5376
5377 if( NULL != cfgState->buf )
5378 {
5379 int rc;
5380 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5381 rc = wait_for_completion_interruptible_timeout(
5382 &pAdapter->tx_action_cnf_event,
5383 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
5384 if(!rc)
5385 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005386 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08005387 ("ERROR: HDD Wait for Action Confirmation Failed!!"));
Jeff Johnson295189b2012-06-20 16:38:30 -07005388 }
5389 }
5390 return;
5391}
Jeff Johnson295189b2012-06-20 16:38:30 -07005392
5393void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5394{
5395 ENTER();
5396 switch ( pAdapter->device_mode )
5397 {
5398 case WLAN_HDD_INFRA_STATION:
5399 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005400 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005401 {
5402 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5403 {
5404 hdd_deinit_tx_rx( pAdapter );
5405 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5406 }
5407
5408 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5409 {
5410 hdd_wmm_adapter_close( pAdapter );
5411 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5412 }
5413
Jeff Johnson295189b2012-06-20 16:38:30 -07005414 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005415#ifdef FEATURE_WLAN_TDLS
5416 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5417 {
5418 wlan_hdd_tdls_exit(pAdapter);
5419 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5420 }
5421#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005422
5423 break;
5424 }
5425
5426 case WLAN_HDD_SOFTAP:
5427 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005428 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305429
5430 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5431 {
5432 hdd_wmm_adapter_close( pAdapter );
5433 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5434 }
5435
Jeff Johnson295189b2012-06-20 16:38:30 -07005436 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005437
5438 hdd_unregister_hostapd(pAdapter);
5439 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005440 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005441 break;
5442 }
5443
5444 case WLAN_HDD_MONITOR:
5445 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005446 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005447 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5448 {
5449 hdd_deinit_tx_rx( pAdapter );
5450 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5451 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005452 if(NULL != pAdapterforTx)
5453 {
5454 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5455 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005456 break;
5457 }
5458
5459
5460 default:
5461 break;
5462 }
5463
5464 EXIT();
5465}
5466
5467void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5468{
5469 struct net_device *pWlanDev = pAdapter->dev;
5470
Rajeev79dbe4c2013-10-05 11:03:42 +05305471#ifdef FEATURE_WLAN_BATCH_SCAN
5472 tHddBatchScanRsp *pNode;
5473 tHddBatchScanRsp *pPrev;
5474 if (pAdapter)
5475 {
Rajeev79dbe4c2013-10-05 11:03:42 +05305476 pNode = pAdapter->pBatchScanRsp;
5477 while (pNode)
5478 {
5479 pPrev = pNode;
5480 pNode = pNode->pNext;
5481 vos_mem_free((v_VOID_t * )pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005482 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05305483 }
5484 pAdapter->pBatchScanRsp = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05305485 }
5486#endif
5487
Jeff Johnson295189b2012-06-20 16:38:30 -07005488 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5489 if( rtnl_held )
5490 {
5491 unregister_netdevice(pWlanDev);
5492 }
5493 else
5494 {
5495 unregister_netdev(pWlanDev);
5496 }
5497 // note that the pAdapter is no longer valid at this point
5498 // since the memory has been reclaimed
5499 }
5500
5501}
5502
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005503void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5504{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305505 VOS_STATUS status;
5506 hdd_adapter_t *pAdapter = NULL;
5507 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005508
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305509 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005510
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305511 /*loop through all adapters.*/
5512 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005513 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305514 pAdapter = pAdapterNode->pAdapter;
5515 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5516 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005517
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305518 { // we skip this registration for modes other than STA and P2P client modes.
5519 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5520 pAdapterNode = pNext;
5521 continue;
5522 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005523
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305524 //Apply Dynamic DTIM For P2P
5525 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5526 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5527 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5528 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5529 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5530 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5531 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5532 (eConnectionState_Associated ==
5533 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5534 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5535 {
5536 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005537
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305538 powerRequest.uIgnoreDTIM = 1;
5539 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5540
5541 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5542 {
5543 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5544 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5545 }
5546 else
5547 {
5548 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5549 }
5550
5551 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5552 * specified during Enter/Exit BMPS when LCD off*/
5553 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5554 NULL, eANI_BOOLEAN_FALSE);
5555 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5556 NULL, eANI_BOOLEAN_FALSE);
5557
5558 /* switch to the DTIM specified in cfg.ini */
5559 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5560 "Switch to DTIM %d", powerRequest.uListenInterval);
5561 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5562 break;
5563
5564 }
5565
5566 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5567 pAdapterNode = pNext;
5568 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005569}
5570
5571void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5572{
5573 /*Switch back to DTIM 1*/
5574 tSirSetPowerParamsReq powerRequest = { 0 };
5575
5576 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5577 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005578 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005579
5580 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5581 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5582 NULL, eANI_BOOLEAN_FALSE);
5583 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5584 NULL, eANI_BOOLEAN_FALSE);
5585
5586 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5587 "Switch to DTIM%d",powerRequest.uListenInterval);
5588 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5589
5590}
5591
Jeff Johnson295189b2012-06-20 16:38:30 -07005592VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5593{
5594 VOS_STATUS status = VOS_STATUS_SUCCESS;
5595
5596 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5597 {
5598 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5599 }
5600
5601 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5602 {
5603 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5604 }
5605
5606 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5607 {
5608 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5609 }
5610
5611 return status;
5612}
5613
5614VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5615{
5616 hdd_adapter_t *pAdapter = NULL;
5617 eHalStatus halStatus;
5618 VOS_STATUS status = VOS_STATUS_E_INVAL;
5619 v_BOOL_t disableBmps = FALSE;
5620 v_BOOL_t disableImps = FALSE;
5621
5622 switch(session_type)
5623 {
5624 case WLAN_HDD_INFRA_STATION:
5625 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005626 case WLAN_HDD_P2P_CLIENT:
5627 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005628 //Exit BMPS -> Is Sta/P2P Client is already connected
5629 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5630 if((NULL != pAdapter)&&
5631 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5632 {
5633 disableBmps = TRUE;
5634 }
5635
5636 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5637 if((NULL != pAdapter)&&
5638 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5639 {
5640 disableBmps = TRUE;
5641 }
5642
5643 //Exit both Bmps and Imps incase of Go/SAP Mode
5644 if((WLAN_HDD_SOFTAP == session_type) ||
5645 (WLAN_HDD_P2P_GO == session_type))
5646 {
5647 disableBmps = TRUE;
5648 disableImps = TRUE;
5649 }
5650
5651 if(TRUE == disableImps)
5652 {
5653 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5654 {
5655 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5656 }
5657 }
5658
5659 if(TRUE == disableBmps)
5660 {
5661 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5662 {
5663 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5664
5665 if(eHAL_STATUS_SUCCESS != halStatus)
5666 {
5667 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005668 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005669 VOS_ASSERT(0);
5670 return status;
5671 }
5672 }
5673
5674 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5675 {
5676 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5677
5678 if(eHAL_STATUS_SUCCESS != halStatus)
5679 {
5680 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005681 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005682 VOS_ASSERT(0);
5683 return status;
5684 }
5685 }
5686 }
5687
5688 if((TRUE == disableBmps) ||
5689 (TRUE == disableImps))
5690 {
5691 /* Now, get the chip into Full Power now */
5692 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5693 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5694 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5695
5696 if(halStatus != eHAL_STATUS_SUCCESS)
5697 {
5698 if(halStatus == eHAL_STATUS_PMC_PENDING)
5699 {
5700 //Block on a completion variable. Can't wait forever though
5701 wait_for_completion_interruptible_timeout(
5702 &pHddCtx->full_pwr_comp_var, msecs_to_jiffies(1000));
5703 }
5704 else
5705 {
5706 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005707 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005708 VOS_ASSERT(0);
5709 return status;
5710 }
5711 }
5712
5713 status = VOS_STATUS_SUCCESS;
5714 }
5715
5716 break;
5717 }
5718 return status;
5719}
5720
5721hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005722 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005723 tANI_U8 rtnl_held )
5724{
5725 hdd_adapter_t *pAdapter = NULL;
5726 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5727 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5728 VOS_STATUS exitbmpsStatus;
5729
Arif Hussain6d2a3322013-11-17 19:50:10 -08005730 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005731
5732 //Disable BMPS incase of Concurrency
5733 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5734
5735 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5736 {
5737 //Fail to Exit BMPS
5738 VOS_ASSERT(0);
5739 return NULL;
5740 }
5741
5742 switch(session_type)
5743 {
5744 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005745 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005746 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005747 {
5748 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5749
5750 if( NULL == pAdapter )
5751 return NULL;
5752
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305753#ifdef FEATURE_WLAN_TDLS
5754 /* A Mutex Lock is introduced while changing/initializing the mode to
5755 * protect the concurrent access for the Adapters by TDLS module.
5756 */
5757 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5758 {
5759 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5760 "%s: unable to lock list", __func__);
5761 return NULL;
5762 }
5763#endif
5764
Jeff Johnsone7245742012-09-05 17:12:55 -07005765 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5766 NL80211_IFTYPE_P2P_CLIENT:
5767 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005768
Jeff Johnson295189b2012-06-20 16:38:30 -07005769 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305770#ifdef FEATURE_WLAN_TDLS
5771 mutex_unlock(&pHddCtx->tdls_lock);
5772#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05305773
5774 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005775 if( VOS_STATUS_SUCCESS != status )
5776 goto err_free_netdev;
5777
5778 status = hdd_register_interface( pAdapter, rtnl_held );
5779 if( VOS_STATUS_SUCCESS != status )
5780 {
5781 hdd_deinit_adapter(pHddCtx, pAdapter);
5782 goto err_free_netdev;
5783 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305784
5785#ifdef WLAN_NS_OFFLOAD
5786 // Workqueue which gets scheduled in IPv6 notification callback.
5787 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5788#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005789 //Stop the Interface TX queue.
5790 netif_tx_disable(pAdapter->dev);
5791 //netif_tx_disable(pWlanDev);
5792 netif_carrier_off(pAdapter->dev);
5793
5794 break;
5795 }
5796
Jeff Johnson295189b2012-06-20 16:38:30 -07005797 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005798 case WLAN_HDD_SOFTAP:
5799 {
5800 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5801 if( NULL == pAdapter )
5802 return NULL;
5803
Jeff Johnson295189b2012-06-20 16:38:30 -07005804 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5805 NL80211_IFTYPE_AP:
5806 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005807 pAdapter->device_mode = session_type;
5808
5809 status = hdd_init_ap_mode(pAdapter);
5810 if( VOS_STATUS_SUCCESS != status )
5811 goto err_free_netdev;
5812
5813 status = hdd_register_hostapd( pAdapter, rtnl_held );
5814 if( VOS_STATUS_SUCCESS != status )
5815 {
5816 hdd_deinit_adapter(pHddCtx, pAdapter);
5817 goto err_free_netdev;
5818 }
5819
5820 netif_tx_disable(pAdapter->dev);
5821 netif_carrier_off(pAdapter->dev);
5822
5823 hdd_set_conparam( 1 );
5824 break;
5825 }
5826 case WLAN_HDD_MONITOR:
5827 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005828 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5829 if( NULL == pAdapter )
5830 return NULL;
5831
5832 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5833 pAdapter->device_mode = session_type;
5834 status = hdd_register_interface( pAdapter, rtnl_held );
5835#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5836 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5837#else
5838 pAdapter->dev->open = hdd_mon_open;
5839 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5840#endif
5841 hdd_init_tx_rx( pAdapter );
5842 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5843 //Set adapter to be used for data tx. It will use either GO or softap.
5844 pAdapter->sessionCtx.monitor.pAdapterForTx =
5845 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005846 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5847 {
5848 pAdapter->sessionCtx.monitor.pAdapterForTx =
5849 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5850 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005851 /* This workqueue will be used to transmit management packet over
5852 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005853 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5854 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5855 return NULL;
5856 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005857
Jeff Johnson295189b2012-06-20 16:38:30 -07005858 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5859 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07005860 }
5861 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005862 case WLAN_HDD_FTM:
5863 {
5864 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5865
5866 if( NULL == pAdapter )
5867 return NULL;
5868 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
5869 * message while loading driver in FTM mode. */
5870 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
5871 pAdapter->device_mode = session_type;
5872 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05305873
5874 hdd_init_tx_rx( pAdapter );
5875
5876 //Stop the Interface TX queue.
5877 netif_tx_disable(pAdapter->dev);
5878 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07005879 }
5880 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07005881 default:
5882 {
5883 VOS_ASSERT(0);
5884 return NULL;
5885 }
5886 }
5887
Jeff Johnson295189b2012-06-20 16:38:30 -07005888 if( VOS_STATUS_SUCCESS == status )
5889 {
5890 //Add it to the hdd's session list.
5891 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
5892 if( NULL == pHddAdapterNode )
5893 {
5894 status = VOS_STATUS_E_NOMEM;
5895 }
5896 else
5897 {
5898 pHddAdapterNode->pAdapter = pAdapter;
5899 status = hdd_add_adapter_back ( pHddCtx,
5900 pHddAdapterNode );
5901 }
5902 }
5903
5904 if( VOS_STATUS_SUCCESS != status )
5905 {
5906 if( NULL != pAdapter )
5907 {
5908 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
5909 pAdapter = NULL;
5910 }
5911 if( NULL != pHddAdapterNode )
5912 {
5913 vos_mem_free( pHddAdapterNode );
5914 }
5915
5916 goto resume_bmps;
5917 }
5918
5919 if(VOS_STATUS_SUCCESS == status)
5920 {
5921 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
5922
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07005923 //Initialize the WoWL service
5924 if(!hdd_init_wowl(pAdapter))
5925 {
5926 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
5927 goto err_free_netdev;
5928 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005929 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005930 return pAdapter;
5931
5932err_free_netdev:
5933 free_netdev(pAdapter->dev);
5934 wlan_hdd_release_intf_addr( pHddCtx,
5935 pAdapter->macAddressCurrent.bytes );
5936
5937resume_bmps:
5938 //If bmps disabled enable it
5939 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
5940 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305941 if (pHddCtx->hdd_wlan_suspended)
5942 {
5943 hdd_set_pwrparams(pHddCtx);
5944 }
5945 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07005946 }
5947 return NULL;
5948}
5949
5950VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
5951 tANI_U8 rtnl_held )
5952{
5953 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
5954 VOS_STATUS status;
5955
5956 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
5957 if( VOS_STATUS_SUCCESS != status )
5958 return status;
5959
5960 while ( pCurrent->pAdapter != pAdapter )
5961 {
5962 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
5963 if( VOS_STATUS_SUCCESS != status )
5964 break;
5965
5966 pCurrent = pNext;
5967 }
5968 pAdapterNode = pCurrent;
5969 if( VOS_STATUS_SUCCESS == status )
5970 {
5971 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
5972 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305973
5974#ifdef FEATURE_WLAN_TDLS
5975
5976 /* A Mutex Lock is introduced while changing/initializing the mode to
5977 * protect the concurrent access for the Adapters by TDLS module.
5978 */
5979 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5980 {
5981 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5982 "%s: unable to lock list", __func__);
5983 return VOS_STATUS_E_FAILURE;
5984 }
5985#endif
5986
Jeff Johnson295189b2012-06-20 16:38:30 -07005987 hdd_remove_adapter( pHddCtx, pAdapterNode );
5988 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08005989 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005990
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305991#ifdef FEATURE_WLAN_TDLS
5992 mutex_unlock(&pHddCtx->tdls_lock);
5993#endif
5994
Jeff Johnson295189b2012-06-20 16:38:30 -07005995
5996 /* If there is a single session of STA/P2P client, re-enable BMPS */
5997 if ((!vos_concurrent_sessions_running()) &&
5998 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
5999 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6000 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306001 if (pHddCtx->hdd_wlan_suspended)
6002 {
6003 hdd_set_pwrparams(pHddCtx);
6004 }
6005 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006006 }
6007
6008 return VOS_STATUS_SUCCESS;
6009 }
6010
6011 return VOS_STATUS_E_FAILURE;
6012}
6013
6014VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6015{
6016 hdd_adapter_list_node_t *pHddAdapterNode;
6017 VOS_STATUS status;
6018
6019 ENTER();
6020
6021 do
6022 {
6023 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6024 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6025 {
6026 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6027 vos_mem_free( pHddAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006028 pHddAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006029 }
6030 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6031
6032 EXIT();
6033
6034 return VOS_STATUS_SUCCESS;
6035}
6036
6037void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6038{
6039 v_U8_t addIE[1] = {0};
6040
6041 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6042 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6043 eANI_BOOLEAN_FALSE) )
6044 {
6045 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006046 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006047 }
6048
6049 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6050 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6051 eANI_BOOLEAN_FALSE) )
6052 {
6053 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006054 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006055 }
6056
6057 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6058 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6059 eANI_BOOLEAN_FALSE) )
6060 {
6061 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006062 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006063 }
6064}
6065
6066VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6067{
6068 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6069 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6070 union iwreq_data wrqu;
6071
6072 ENTER();
6073
6074 switch(pAdapter->device_mode)
6075 {
6076 case WLAN_HDD_INFRA_STATION:
6077 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006078 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006079 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6080 {
6081 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6082 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6083 pAdapter->sessionId,
6084 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6085 else
6086 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6087 pAdapter->sessionId,
6088 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6089 //success implies disconnect command got queued up successfully
6090 if(halStatus == eHAL_STATUS_SUCCESS)
6091 {
6092 wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
6093 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6094 }
6095 memset(&wrqu, '\0', sizeof(wrqu));
6096 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6097 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6098 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6099 }
6100 else
6101 {
Madan Mohan Koyyalamudiff3a7152013-06-13 14:47:55 +05306102 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07006103 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306104#ifdef WLAN_OPEN_SOURCE
6105#ifdef WLAN_NS_OFFLOAD
6106 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6107#endif
6108#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006109
6110 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6111 {
6112 INIT_COMPLETION(pAdapter->session_close_comp_var);
6113 if (eHAL_STATUS_SUCCESS ==
6114 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6115 hdd_smeCloseSessionCallback, pAdapter))
6116 {
6117 //Block on a completion variable. Can't wait forever though.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07006118 wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006119 &pAdapter->session_close_comp_var,
6120 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
6121 }
6122 }
6123
6124 break;
6125
6126 case WLAN_HDD_SOFTAP:
6127 case WLAN_HDD_P2P_GO:
6128 //Any softap specific cleanup here...
6129 mutex_lock(&pHddCtx->sap_lock);
6130 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6131 {
6132 VOS_STATUS status;
6133 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6134
6135 //Stop Bss.
6136 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6137 if (VOS_IS_STATUS_SUCCESS(status))
6138 {
6139 hdd_hostapd_state_t *pHostapdState =
6140 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6141
6142 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6143
6144 if (!VOS_IS_STATUS_SUCCESS(status))
6145 {
6146 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006147 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006148 }
6149 }
6150 else
6151 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006152 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006153 }
6154 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6155
6156 if (eHAL_STATUS_FAILURE ==
6157 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6158 0, NULL, eANI_BOOLEAN_FALSE))
6159 {
6160 hddLog(LOGE,
6161 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006162 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006163 }
6164
6165 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6166 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6167 eANI_BOOLEAN_FALSE) )
6168 {
6169 hddLog(LOGE,
6170 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6171 }
6172
6173 // Reset WNI_CFG_PROBE_RSP Flags
6174 wlan_hdd_reset_prob_rspies(pAdapter);
6175 kfree(pAdapter->sessionCtx.ap.beacon);
6176 pAdapter->sessionCtx.ap.beacon = NULL;
6177 }
6178 mutex_unlock(&pHddCtx->sap_lock);
6179 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006180
Jeff Johnson295189b2012-06-20 16:38:30 -07006181 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006182#ifdef WLAN_OPEN_SOURCE
6183 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6184#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006185 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006186
Jeff Johnson295189b2012-06-20 16:38:30 -07006187 default:
6188 break;
6189 }
6190
6191 EXIT();
6192 return VOS_STATUS_SUCCESS;
6193}
6194
6195VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6196{
6197 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6198 VOS_STATUS status;
6199 hdd_adapter_t *pAdapter;
6200
6201 ENTER();
6202
6203 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6204
6205 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6206 {
6207 pAdapter = pAdapterNode->pAdapter;
6208 netif_tx_disable(pAdapter->dev);
6209 netif_carrier_off(pAdapter->dev);
6210
6211 hdd_stop_adapter( pHddCtx, pAdapter );
6212
6213 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6214 pAdapterNode = pNext;
6215 }
6216
6217 EXIT();
6218
6219 return VOS_STATUS_SUCCESS;
6220}
6221
6222VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6223{
6224 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6225 VOS_STATUS status;
6226 hdd_adapter_t *pAdapter;
6227
6228 ENTER();
6229
6230 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6231
6232 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6233 {
6234 pAdapter = pAdapterNode->pAdapter;
6235 netif_tx_disable(pAdapter->dev);
6236 netif_carrier_off(pAdapter->dev);
6237
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006238 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6239
Jeff Johnson295189b2012-06-20 16:38:30 -07006240 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306241 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6242 {
6243 hdd_wmm_adapter_close( pAdapter );
6244 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6245 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006246
6247 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6248 pAdapterNode = pNext;
6249 }
6250
6251 EXIT();
6252
6253 return VOS_STATUS_SUCCESS;
6254}
6255
6256VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6257{
6258 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6259 VOS_STATUS status;
6260 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306261 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006262
6263 ENTER();
6264
6265 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6266
6267 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6268 {
6269 pAdapter = pAdapterNode->pAdapter;
6270
6271 switch(pAdapter->device_mode)
6272 {
6273 case WLAN_HDD_INFRA_STATION:
6274 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006275 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306276
6277 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6278
Jeff Johnson295189b2012-06-20 16:38:30 -07006279 hdd_init_station_mode(pAdapter);
6280 /* Open the gates for HDD to receive Wext commands */
6281 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006282 pHddCtx->scan_info.mScanPending = FALSE;
6283 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006284
6285 //Trigger the initial scan
6286 hdd_wlan_initial_scan(pAdapter);
6287
6288 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306289 if (eConnectionState_Associated == connState ||
6290 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006291 {
6292 union iwreq_data wrqu;
6293 memset(&wrqu, '\0', sizeof(wrqu));
6294 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6295 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6296 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006297 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006298
Jeff Johnson295189b2012-06-20 16:38:30 -07006299 /* indicate disconnected event to nl80211 */
6300 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6301 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006302 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306303 else if (eConnectionState_Connecting == connState)
6304 {
6305 /*
6306 * Indicate connect failure to supplicant if we were in the
6307 * process of connecting
6308 */
6309 cfg80211_connect_result(pAdapter->dev, NULL,
6310 NULL, 0, NULL, 0,
6311 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6312 GFP_KERNEL);
6313 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006314 break;
6315
6316 case WLAN_HDD_SOFTAP:
6317 /* softAP can handle SSR */
6318 break;
6319
6320 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006321 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006322 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006323 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006324 break;
6325
6326 case WLAN_HDD_MONITOR:
6327 /* monitor interface start */
6328 break;
6329 default:
6330 break;
6331 }
6332
6333 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6334 pAdapterNode = pNext;
6335 }
6336
6337 EXIT();
6338
6339 return VOS_STATUS_SUCCESS;
6340}
6341
6342VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6343{
6344 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6345 hdd_adapter_t *pAdapter;
6346 VOS_STATUS status;
6347 v_U32_t roamId;
6348
6349 ENTER();
6350
6351 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6352
6353 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6354 {
6355 pAdapter = pAdapterNode->pAdapter;
6356
6357 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6358 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6359 {
6360 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6361 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6362
6363 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6364 init_completion(&pAdapter->disconnect_comp_var);
6365 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6366 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6367
6368 wait_for_completion_interruptible_timeout(
6369 &pAdapter->disconnect_comp_var,
6370 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6371
6372 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6373 pHddCtx->isAmpAllowed = VOS_FALSE;
6374 sme_RoamConnect(pHddCtx->hHal,
6375 pAdapter->sessionId, &(pWextState->roamProfile),
6376 &roamId);
6377 }
6378
6379 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6380 pAdapterNode = pNext;
6381 }
6382
6383 EXIT();
6384
6385 return VOS_STATUS_SUCCESS;
6386}
6387
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006388void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6389{
6390 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6391 VOS_STATUS status;
6392 hdd_adapter_t *pAdapter;
6393 hdd_station_ctx_t *pHddStaCtx;
6394 hdd_ap_ctx_t *pHddApCtx;
6395 hdd_hostapd_state_t * pHostapdState;
6396 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6397 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6398 const char *p2pMode = "DEV";
6399 const char *ccMode = "Standalone";
6400 int n;
6401
6402 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6403 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6404 {
6405 pAdapter = pAdapterNode->pAdapter;
6406 switch (pAdapter->device_mode) {
6407 case WLAN_HDD_INFRA_STATION:
6408 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6409 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6410 staChannel = pHddStaCtx->conn_info.operationChannel;
6411 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6412 }
6413 break;
6414 case WLAN_HDD_P2P_CLIENT:
6415 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6416 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6417 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6418 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6419 p2pMode = "CLI";
6420 }
6421 break;
6422 case WLAN_HDD_P2P_GO:
6423 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6424 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6425 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6426 p2pChannel = pHddApCtx->operatingChannel;
6427 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6428 }
6429 p2pMode = "GO";
6430 break;
6431 case WLAN_HDD_SOFTAP:
6432 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6433 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6434 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6435 apChannel = pHddApCtx->operatingChannel;
6436 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6437 }
6438 break;
6439 default:
6440 break;
6441 }
6442 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6443 pAdapterNode = pNext;
6444 }
6445 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6446 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6447 }
6448 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6449 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6450 if (p2pChannel > 0) {
6451 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6452 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6453 }
6454 if (apChannel > 0) {
6455 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6456 apChannel, MAC_ADDR_ARRAY(apBssid));
6457 }
6458
6459 if (p2pChannel > 0 && apChannel > 0) {
6460 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6461 }
6462}
6463
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006464bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006465{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006466 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006467}
6468
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006469/* Once SSR is disabled then it cannot be set. */
6470void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006471{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006472 if (HDD_SSR_DISABLED == isSsrRequired)
6473 return;
6474
Jeff Johnson295189b2012-06-20 16:38:30 -07006475 isSsrRequired = value;
6476}
6477
6478VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6479 hdd_adapter_list_node_t** ppAdapterNode)
6480{
6481 VOS_STATUS status;
6482 spin_lock(&pHddCtx->hddAdapters.lock);
6483 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6484 (hdd_list_node_t**) ppAdapterNode );
6485 spin_unlock(&pHddCtx->hddAdapters.lock);
6486 return status;
6487}
6488
6489VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6490 hdd_adapter_list_node_t* pAdapterNode,
6491 hdd_adapter_list_node_t** pNextAdapterNode)
6492{
6493 VOS_STATUS status;
6494 spin_lock(&pHddCtx->hddAdapters.lock);
6495 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6496 (hdd_list_node_t*) pAdapterNode,
6497 (hdd_list_node_t**)pNextAdapterNode );
6498
6499 spin_unlock(&pHddCtx->hddAdapters.lock);
6500 return status;
6501}
6502
6503VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6504 hdd_adapter_list_node_t* pAdapterNode)
6505{
6506 VOS_STATUS status;
6507 spin_lock(&pHddCtx->hddAdapters.lock);
6508 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6509 &pAdapterNode->node );
6510 spin_unlock(&pHddCtx->hddAdapters.lock);
6511 return status;
6512}
6513
6514VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6515 hdd_adapter_list_node_t** ppAdapterNode)
6516{
6517 VOS_STATUS status;
6518 spin_lock(&pHddCtx->hddAdapters.lock);
6519 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6520 (hdd_list_node_t**) ppAdapterNode );
6521 spin_unlock(&pHddCtx->hddAdapters.lock);
6522 return status;
6523}
6524
6525VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6526 hdd_adapter_list_node_t* pAdapterNode)
6527{
6528 VOS_STATUS status;
6529 spin_lock(&pHddCtx->hddAdapters.lock);
6530 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6531 (hdd_list_node_t*) pAdapterNode );
6532 spin_unlock(&pHddCtx->hddAdapters.lock);
6533 return status;
6534}
6535
6536VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6537 hdd_adapter_list_node_t* pAdapterNode)
6538{
6539 VOS_STATUS status;
6540 spin_lock(&pHddCtx->hddAdapters.lock);
6541 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6542 (hdd_list_node_t*) pAdapterNode );
6543 spin_unlock(&pHddCtx->hddAdapters.lock);
6544 return status;
6545}
6546
6547hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6548 tSirMacAddr macAddr )
6549{
6550 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6551 hdd_adapter_t *pAdapter;
6552 VOS_STATUS status;
6553
6554 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6555
6556 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6557 {
6558 pAdapter = pAdapterNode->pAdapter;
6559
6560 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6561 macAddr, sizeof(tSirMacAddr) ) )
6562 {
6563 return pAdapter;
6564 }
6565 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6566 pAdapterNode = pNext;
6567 }
6568
6569 return NULL;
6570
6571}
6572
6573hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6574{
6575 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6576 hdd_adapter_t *pAdapter;
6577 VOS_STATUS status;
6578
6579 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6580
6581 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6582 {
6583 pAdapter = pAdapterNode->pAdapter;
6584
6585 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6586 IFNAMSIZ ) )
6587 {
6588 return pAdapter;
6589 }
6590 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6591 pAdapterNode = pNext;
6592 }
6593
6594 return NULL;
6595
6596}
6597
6598hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6599{
6600 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6601 hdd_adapter_t *pAdapter;
6602 VOS_STATUS status;
6603
6604 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6605
6606 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6607 {
6608 pAdapter = pAdapterNode->pAdapter;
6609
6610 if( pAdapter && (mode == pAdapter->device_mode) )
6611 {
6612 return pAdapter;
6613 }
6614 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6615 pAdapterNode = pNext;
6616 }
6617
6618 return NULL;
6619
6620}
6621
6622//Remove this function later
6623hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6624{
6625 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6626 hdd_adapter_t *pAdapter;
6627 VOS_STATUS status;
6628
6629 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6630
6631 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6632 {
6633 pAdapter = pAdapterNode->pAdapter;
6634
6635 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6636 {
6637 return pAdapter;
6638 }
6639
6640 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6641 pAdapterNode = pNext;
6642 }
6643
6644 return NULL;
6645
6646}
6647
Jeff Johnson295189b2012-06-20 16:38:30 -07006648/**---------------------------------------------------------------------------
6649
6650 \brief hdd_set_monitor_tx_adapter() -
6651
6652 This API initializes the adapter to be used while transmitting on monitor
6653 adapter.
6654
6655 \param - pHddCtx - Pointer to the HDD context.
6656 pAdapter - Adapter that will used for TX. This can be NULL.
6657 \return - None.
6658 --------------------------------------------------------------------------*/
6659void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6660{
6661 hdd_adapter_t *pMonAdapter;
6662
6663 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6664
6665 if( NULL != pMonAdapter )
6666 {
6667 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6668 }
6669}
Jeff Johnson295189b2012-06-20 16:38:30 -07006670/**---------------------------------------------------------------------------
6671
6672 \brief hdd_select_queue() -
6673
6674 This API returns the operating channel of the requested device mode
6675
6676 \param - pHddCtx - Pointer to the HDD context.
6677 - mode - Device mode for which operating channel is required
6678 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6679 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6680 \return - channel number. "0" id the requested device is not found OR it is not connected.
6681 --------------------------------------------------------------------------*/
6682v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6683{
6684 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6685 VOS_STATUS status;
6686 hdd_adapter_t *pAdapter;
6687 v_U8_t operatingChannel = 0;
6688
6689 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6690
6691 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6692 {
6693 pAdapter = pAdapterNode->pAdapter;
6694
6695 if( mode == pAdapter->device_mode )
6696 {
6697 switch(pAdapter->device_mode)
6698 {
6699 case WLAN_HDD_INFRA_STATION:
6700 case WLAN_HDD_P2P_CLIENT:
6701 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6702 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6703 break;
6704 case WLAN_HDD_SOFTAP:
6705 case WLAN_HDD_P2P_GO:
6706 /*softap connection info */
6707 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6708 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6709 break;
6710 default:
6711 break;
6712 }
6713
6714 break; //Found the device of interest. break the loop
6715 }
6716
6717 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6718 pAdapterNode = pNext;
6719 }
6720 return operatingChannel;
6721}
6722
6723#ifdef WLAN_FEATURE_PACKET_FILTERING
6724/**---------------------------------------------------------------------------
6725
6726 \brief hdd_set_multicast_list() -
6727
6728 This used to set the multicast address list.
6729
6730 \param - dev - Pointer to the WLAN device.
6731 - skb - Pointer to OS packet (sk_buff).
6732 \return - success/fail
6733
6734 --------------------------------------------------------------------------*/
6735static void hdd_set_multicast_list(struct net_device *dev)
6736{
6737 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006738 int mc_count;
6739 int i = 0;
6740 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306741
6742 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006743 {
6744 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306745 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006746 return;
6747 }
6748
6749 if (dev->flags & IFF_ALLMULTI)
6750 {
6751 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006752 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306753 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006754 }
6755 else
6756 {
6757 mc_count = netdev_mc_count(dev);
6758 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006759 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006760 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6761 {
6762 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006763 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306764 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006765 return;
6766 }
6767
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306768 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07006769
6770 netdev_for_each_mc_addr(ha, dev) {
6771 if (i == mc_count)
6772 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306773 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
6774 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08006775 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07006776 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306777 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07006778 i++;
6779 }
6780 }
6781 return;
6782}
6783#endif
6784
6785/**---------------------------------------------------------------------------
6786
6787 \brief hdd_select_queue() -
6788
6789 This function is registered with the Linux OS for network
6790 core to decide which queue to use first.
6791
6792 \param - dev - Pointer to the WLAN device.
6793 - skb - Pointer to OS packet (sk_buff).
6794 \return - ac, Queue Index/access category corresponding to UP in IP header
6795
6796 --------------------------------------------------------------------------*/
6797v_U16_t hdd_select_queue(struct net_device *dev,
6798 struct sk_buff *skb)
6799{
6800 return hdd_wmm_select_queue(dev, skb);
6801}
6802
6803
6804/**---------------------------------------------------------------------------
6805
6806 \brief hdd_wlan_initial_scan() -
6807
6808 This function triggers the initial scan
6809
6810 \param - pAdapter - Pointer to the HDD adapter.
6811
6812 --------------------------------------------------------------------------*/
6813void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
6814{
6815 tCsrScanRequest scanReq;
6816 tCsrChannelInfo channelInfo;
6817 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07006818 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07006819 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6820
6821 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
6822 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
6823 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
6824
6825 if(sme_Is11dSupported(pHddCtx->hHal))
6826 {
6827 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
6828 if ( HAL_STATUS_SUCCESS( halStatus ) )
6829 {
6830 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
6831 if( !scanReq.ChannelInfo.ChannelList )
6832 {
6833 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
6834 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006835 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006836 return;
6837 }
6838 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
6839 channelInfo.numOfChannels);
6840 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
6841 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006842 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006843 }
6844
6845 scanReq.scanType = eSIR_PASSIVE_SCAN;
6846 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
6847 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
6848 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
6849 }
6850 else
6851 {
6852 scanReq.scanType = eSIR_ACTIVE_SCAN;
6853 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
6854 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
6855 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
6856 }
6857
6858 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
6859 if ( !HAL_STATUS_SUCCESS( halStatus ) )
6860 {
6861 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
6862 __func__, halStatus );
6863 }
6864
6865 if(sme_Is11dSupported(pHddCtx->hHal))
6866 vos_mem_free(scanReq.ChannelInfo.ChannelList);
6867}
6868
6869struct fullPowerContext
6870{
6871 struct completion completion;
6872 unsigned int magic;
6873};
6874#define POWER_CONTEXT_MAGIC 0x504F5752 //POWR
6875
6876/**---------------------------------------------------------------------------
6877
6878 \brief hdd_full_power_callback() - HDD full power callback function
6879
6880 This is the function invoked by SME to inform the result of a full power
6881 request issued by HDD
6882
6883 \param - callbackcontext - Pointer to cookie
6884 \param - status - result of request
6885
6886 \return - None
6887
6888 --------------------------------------------------------------------------*/
6889static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
6890{
6891 struct fullPowerContext *pContext = callbackContext;
6892
6893 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05306894 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006895
6896 if (NULL == callbackContext)
6897 {
6898 hddLog(VOS_TRACE_LEVEL_ERROR,
6899 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006900 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07006901 return;
6902 }
6903
6904 /* there is a race condition that exists between this callback function
6905 and the caller since the caller could time out either before or
6906 while this code is executing. we'll assume the timeout hasn't
6907 occurred, but we'll verify that right before we save our work */
6908
6909 if (POWER_CONTEXT_MAGIC != pContext->magic)
6910 {
6911 /* the caller presumably timed out so there is nothing we can do */
6912 hddLog(VOS_TRACE_LEVEL_WARN,
6913 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006914 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07006915 return;
6916 }
6917
6918 /* the race is on. caller could have timed out immediately after
6919 we verified the magic, but if so, caller will wait a short time
6920 for us to notify the caller, so the context will stay valid */
6921 complete(&pContext->completion);
6922}
6923
6924/**---------------------------------------------------------------------------
6925
6926 \brief hdd_wlan_exit() - HDD WLAN exit function
6927
6928 This is the driver exit point (invoked during rmmod)
6929
6930 \param - pHddCtx - Pointer to the HDD Context
6931
6932 \return - None
6933
6934 --------------------------------------------------------------------------*/
6935void hdd_wlan_exit(hdd_context_t *pHddCtx)
6936{
6937 eHalStatus halStatus;
6938 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
6939 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05306940 struct wiphy *wiphy = pHddCtx->wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07006941 hdd_adapter_t* pAdapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07006942 struct fullPowerContext powerContext;
6943 long lrc;
6944
6945 ENTER();
6946
Jeff Johnson88ba7742013-02-27 14:36:02 -08006947 if (VOS_FTM_MODE != hdd_get_conparam())
6948 {
6949 // Unloading, restart logic is no more required.
6950 wlan_hdd_restart_deinit(pHddCtx);
6951 }
Jeff Johnsone7245742012-09-05 17:12:55 -07006952
Jeff Johnson295189b2012-06-20 16:38:30 -07006953 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006954 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006955 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006956 {
6957 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
6958 WLAN_HDD_INFRA_STATION);
6959 if (pAdapter == NULL)
6960 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
6961
6962 if (pAdapter != NULL)
6963 {
6964 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
6965 hdd_UnregisterWext(pAdapter->dev);
6966 }
6967 }
6968 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006969
Jeff Johnson295189b2012-06-20 16:38:30 -07006970 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08006971 {
6972 wlan_hdd_ftm_close(pHddCtx);
6973 goto free_hdd_ctx;
6974 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006975 //Stop the Interface TX queue.
6976 //netif_tx_disable(pWlanDev);
6977 //netif_carrier_off(pWlanDev);
6978
Jeff Johnson295189b2012-06-20 16:38:30 -07006979 if (VOS_STA_SAP_MODE == hdd_get_conparam())
6980 {
6981 pAdapter = hdd_get_adapter(pHddCtx,
6982 WLAN_HDD_SOFTAP);
6983 }
6984 else
6985 {
Jeff Johnson295189b2012-06-20 16:38:30 -07006986 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07006987 {
6988 pAdapter = hdd_get_adapter(pHddCtx,
6989 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07006990 if (pAdapter == NULL)
6991 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07006992 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006993 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006994 /* DeRegister with platform driver as client for Suspend/Resume */
6995 vosStatus = hddDeregisterPmOps(pHddCtx);
6996 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
6997 {
6998 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
6999 VOS_ASSERT(0);
7000 }
7001
7002 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7003 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7004 {
7005 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7006 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007007
7008 // Cancel any outstanding scan requests. We are about to close all
7009 // of our adapters, but an adapter structure is what SME passes back
7010 // to our callback function. Hence if there are any outstanding scan
7011 // requests then there is a race condition between when the adapter
7012 // is closed and when the callback is invoked. We try to resolve that
7013 // race condition here by canceling any outstanding scans before we
7014 // close the adapters.
7015 // Note that the scans may be cancelled in an asynchronous manner, so
7016 // ideally there needs to be some kind of synchronization. Rather than
7017 // introduce a new synchronization here, we will utilize the fact that
7018 // we are about to Request Full Power, and since that is synchronized,
7019 // the expectation is that by the time Request Full Power has completed,
7020 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007021 if (NULL != pAdapter)
7022 hdd_abort_mac_scan( pHddCtx, pAdapter->sessionId);
7023 else
7024 hddLog(VOS_TRACE_LEVEL_ERROR,
7025 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007026
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007027 //Stop the traffic monitor timer
7028 if ( VOS_TIMER_STATE_RUNNING ==
7029 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7030 {
7031 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7032 }
7033
7034 // Destroy the traffic monitor timer
7035 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7036 &pHddCtx->tx_rx_trafficTmr)))
7037 {
7038 hddLog(VOS_TRACE_LEVEL_ERROR,
7039 "%s: Cannot deallocate Traffic monitor timer", __func__);
7040 }
7041
Jeff Johnson295189b2012-06-20 16:38:30 -07007042 //Disable IMPS/BMPS as we do not want the device to enter any power
7043 //save mode during shutdown
7044 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7045 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7046 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7047
7048 //Ensure that device is in full power as we will touch H/W during vos_Stop
7049 init_completion(&powerContext.completion);
7050 powerContext.magic = POWER_CONTEXT_MAGIC;
7051
7052 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7053 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7054
7055 if (eHAL_STATUS_SUCCESS != halStatus)
7056 {
7057 if (eHAL_STATUS_PMC_PENDING == halStatus)
7058 {
7059 /* request was sent -- wait for the response */
7060 lrc = wait_for_completion_interruptible_timeout(
7061 &powerContext.completion,
7062 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
7063 /* either we have a response or we timed out
7064 either way, first invalidate our magic */
7065 powerContext.magic = 0;
7066 if (lrc <= 0)
7067 {
7068 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007069 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007070 /* there is a race condition such that the callback
7071 function could be executing at the same time we are. of
7072 primary concern is if the callback function had already
7073 verified the "magic" but hasn't yet set the completion
7074 variable. Since the completion variable is on our
7075 stack, we'll delay just a bit to make sure the data is
7076 still valid if that is the case */
7077 msleep(50);
7078 }
7079 }
7080 else
7081 {
7082 hddLog(VOS_TRACE_LEVEL_ERROR,
7083 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007084 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007085 VOS_ASSERT(0);
7086 /* continue -- need to clean up as much as possible */
7087 }
7088 }
7089
Yue Ma0d4891e2013-08-06 17:01:45 -07007090 hdd_debugfs_exit(pHddCtx);
7091
Jeff Johnson295189b2012-06-20 16:38:30 -07007092 // Unregister the Net Device Notifier
7093 unregister_netdevice_notifier(&hdd_netdev_notifier);
7094
Jeff Johnson295189b2012-06-20 16:38:30 -07007095 hdd_stop_all_adapters( pHddCtx );
7096
Jeff Johnson295189b2012-06-20 16:38:30 -07007097#ifdef WLAN_BTAMP_FEATURE
7098 vosStatus = WLANBAP_Stop(pVosContext);
7099 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7100 {
7101 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7102 "%s: Failed to stop BAP",__func__);
7103 }
7104#endif //WLAN_BTAMP_FEATURE
7105
7106 //Stop all the modules
7107 vosStatus = vos_stop( pVosContext );
7108 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7109 {
7110 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7111 "%s: Failed to stop VOSS",__func__);
7112 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7113 }
7114
Jeff Johnson295189b2012-06-20 16:38:30 -07007115 //Assert Deep sleep signal now to put Libra HW in lowest power state
7116 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7117 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7118
7119 //Vote off any PMIC voltage supplies
7120 vos_chipPowerDown(NULL, NULL, NULL);
7121
7122 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7123
Leo Chang59cdc7e2013-07-10 10:08:21 -07007124
Jeff Johnson295189b2012-06-20 16:38:30 -07007125 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007126 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007127
7128 //Close the scheduler before calling vos_close to make sure no thread is
7129 // scheduled after the each module close is called i.e after all the data
7130 // structures are freed.
7131 vosStatus = vos_sched_close( pVosContext );
7132 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7133 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7134 "%s: Failed to close VOSS Scheduler",__func__);
7135 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7136 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007137#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007138#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7139 /* Destroy the wake lock */
7140 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7141#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007142 /* Destroy the wake lock */
7143 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007144#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007145
7146 //Close VOSS
7147 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7148 vos_close(pVosContext);
7149
Jeff Johnson295189b2012-06-20 16:38:30 -07007150 //Close Watchdog
7151 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7152 vos_watchdog_close(pVosContext);
7153
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307154 //Clean up HDD Nlink Service
7155 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007156#ifdef WLAN_KD_READY_NOTIFIER
7157 nl_srv_exit(pHddCtx->ptt_pid);
7158#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307159 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007160#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307161
Jeff Johnson295189b2012-06-20 16:38:30 -07007162 /* Cancel the vote for XO Core ON.
7163 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7164 * exited at this point
7165 */
7166 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007167 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007168 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7169 {
7170 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7171 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007172 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007173 }
7174
7175 hdd_close_all_adapters( pHddCtx );
7176
7177
7178 //Free up dynamically allocated members inside HDD Adapter
7179 kfree(pHddCtx->cfg_ini);
7180 pHddCtx->cfg_ini= NULL;
7181
7182 /* free the power on lock from platform driver */
7183 if (free_riva_power_on_lock("wlan"))
7184 {
7185 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7186 __func__);
7187 }
7188
Jeff Johnson88ba7742013-02-27 14:36:02 -08007189free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007190 /* FTM mode, WIPHY did not registered
7191 If un-register here, system crash will happen */
7192 if (VOS_FTM_MODE != hdd_get_conparam())
7193 {
7194 wiphy_unregister(wiphy) ;
7195 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007196 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007197 if (hdd_is_ssr_required())
7198 {
7199 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007200 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007201 msleep(5000);
7202 }
7203 hdd_set_ssr_required (VOS_FALSE);
7204}
7205
7206
7207/**---------------------------------------------------------------------------
7208
7209 \brief hdd_update_config_from_nv() - Function to update the contents of
7210 the running configuration with parameters taken from NV storage
7211
7212 \param - pHddCtx - Pointer to the HDD global context
7213
7214 \return - VOS_STATUS_SUCCESS if successful
7215
7216 --------------------------------------------------------------------------*/
7217static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7218{
Jeff Johnson295189b2012-06-20 16:38:30 -07007219 v_BOOL_t itemIsValid = VOS_FALSE;
7220 VOS_STATUS status;
7221 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7222 v_U8_t macLoop;
7223
7224 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7225 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7226 if(status != VOS_STATUS_SUCCESS)
7227 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007228 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007229 return VOS_STATUS_E_FAILURE;
7230 }
7231
7232 if (itemIsValid == VOS_TRUE)
7233 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007234 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007235 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7236 VOS_MAX_CONCURRENCY_PERSONA);
7237 if(status != VOS_STATUS_SUCCESS)
7238 {
7239 /* Get MAC from NV fail, not update CFG info
7240 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007241 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007242 return VOS_STATUS_E_FAILURE;
7243 }
7244
7245 /* If first MAC is not valid, treat all others are not valid
7246 * Then all MACs will be got from ini file */
7247 if(vos_is_macaddr_zero(&macFromNV[0]))
7248 {
7249 /* MAC address in NV file is not configured yet */
7250 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7251 return VOS_STATUS_E_INVAL;
7252 }
7253
7254 /* Get MAC address from NV, update CFG info */
7255 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7256 {
7257 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7258 {
7259 printk(KERN_ERR "not valid MAC from NV for %d", macLoop);
7260 /* This MAC is not valid, skip it
7261 * This MAC will be got from ini file */
7262 }
7263 else
7264 {
7265 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7266 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7267 VOS_MAC_ADDR_SIZE);
7268 }
7269 }
7270 }
7271 else
7272 {
7273 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7274 return VOS_STATUS_E_FAILURE;
7275 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007276
Jeff Johnson295189b2012-06-20 16:38:30 -07007277
7278 return VOS_STATUS_SUCCESS;
7279}
7280
7281/**---------------------------------------------------------------------------
7282
7283 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7284
7285 \param - pAdapter - Pointer to the HDD
7286
7287 \return - None
7288
7289 --------------------------------------------------------------------------*/
7290VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7291{
7292 eHalStatus halStatus;
7293 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307294 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007295
Jeff Johnson295189b2012-06-20 16:38:30 -07007296
7297 // Send ready indication to the HDD. This will kick off the MAC
7298 // into a 'running' state and should kick off an initial scan.
7299 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7300 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7301 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307302 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007303 "code %08d [x%08x]",__func__, halStatus, halStatus );
7304 return VOS_STATUS_E_FAILURE;
7305 }
7306
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307307 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007308 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7309 // And RIVA will crash
7310 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7311 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307312 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7313 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7314
7315
Jeff Johnson295189b2012-06-20 16:38:30 -07007316 return VOS_STATUS_SUCCESS;
7317}
7318
Jeff Johnson295189b2012-06-20 16:38:30 -07007319/* wake lock APIs for HDD */
7320void hdd_prevent_suspend(void)
7321{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007322#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007323 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007324#else
7325 wcnss_prevent_suspend();
7326#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007327}
7328
7329void hdd_allow_suspend(void)
7330{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007331#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007332 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007333#else
7334 wcnss_allow_suspend();
7335#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007336}
7337
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007338void hdd_allow_suspend_timeout(v_U32_t timeout)
7339{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007340#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007341 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007342#else
7343 /* Do nothing as there is no API in wcnss for timeout*/
7344#endif
7345}
7346
Jeff Johnson295189b2012-06-20 16:38:30 -07007347/**---------------------------------------------------------------------------
7348
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007349 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7350 information between Host and Riva
7351
7352 This function gets reported version of FW
7353 It also finds the version of Riva headers used to compile the host
7354 It compares the above two and prints a warning if they are different
7355 It gets the SW and HW version string
7356 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7357 indicating the features they support through a bitmap
7358
7359 \param - pHddCtx - Pointer to HDD context
7360
7361 \return - void
7362
7363 --------------------------------------------------------------------------*/
7364
7365void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7366{
7367
7368 tSirVersionType versionCompiled;
7369 tSirVersionType versionReported;
7370 tSirVersionString versionString;
7371 tANI_U8 fwFeatCapsMsgSupported = 0;
7372 VOS_STATUS vstatus;
7373
7374 /* retrieve and display WCNSS version information */
7375 do {
7376
7377 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7378 &versionCompiled);
7379 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7380 {
7381 hddLog(VOS_TRACE_LEVEL_FATAL,
7382 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007383 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007384 break;
7385 }
7386
7387 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7388 &versionReported);
7389 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7390 {
7391 hddLog(VOS_TRACE_LEVEL_FATAL,
7392 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007393 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007394 break;
7395 }
7396
7397 if ((versionCompiled.major != versionReported.major) ||
7398 (versionCompiled.minor != versionReported.minor) ||
7399 (versionCompiled.version != versionReported.version) ||
7400 (versionCompiled.revision != versionReported.revision))
7401 {
7402 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7403 "Host expected %u.%u.%u.%u\n",
7404 WLAN_MODULE_NAME,
7405 (int)versionReported.major,
7406 (int)versionReported.minor,
7407 (int)versionReported.version,
7408 (int)versionReported.revision,
7409 (int)versionCompiled.major,
7410 (int)versionCompiled.minor,
7411 (int)versionCompiled.version,
7412 (int)versionCompiled.revision);
7413 }
7414 else
7415 {
7416 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7417 WLAN_MODULE_NAME,
7418 (int)versionReported.major,
7419 (int)versionReported.minor,
7420 (int)versionReported.version,
7421 (int)versionReported.revision);
7422 }
7423
7424 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7425 versionString,
7426 sizeof(versionString));
7427 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7428 {
7429 hddLog(VOS_TRACE_LEVEL_FATAL,
7430 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007431 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007432 break;
7433 }
7434
7435 pr_info("%s: WCNSS software version %s\n",
7436 WLAN_MODULE_NAME, versionString);
7437
7438 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7439 versionString,
7440 sizeof(versionString));
7441 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7442 {
7443 hddLog(VOS_TRACE_LEVEL_FATAL,
7444 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007445 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007446 break;
7447 }
7448
7449 pr_info("%s: WCNSS hardware version %s\n",
7450 WLAN_MODULE_NAME, versionString);
7451
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007452 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7453 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007454 send the message only if it the riva is 1.1
7455 minor numbers for different riva branches:
7456 0 -> (1.0)Mainline Build
7457 1 -> (1.1)Mainline Build
7458 2->(1.04) Stability Build
7459 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007460 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007461 ((versionReported.minor>=1) && (versionReported.version>=1)))
7462 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7463 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007464
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007465 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007466 {
7467#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7468 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7469 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7470#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007471 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7472 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7473 {
7474 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7475 }
7476
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007477 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007478 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007479
7480 } while (0);
7481
7482}
7483
7484/**---------------------------------------------------------------------------
7485
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307486 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7487
7488 \param - pHddCtx - Pointer to the hdd context
7489
7490 \return - true if hardware supports 5GHz
7491
7492 --------------------------------------------------------------------------*/
7493static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7494{
7495 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7496 * then hardware support 5Ghz.
7497 */
7498 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7499 {
7500 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__);
7501 return true;
7502 }
7503 else
7504 {
7505 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz",
7506 __func__);
7507 return false;
7508 }
7509}
7510
7511
7512/**---------------------------------------------------------------------------
7513
Jeff Johnson295189b2012-06-20 16:38:30 -07007514 \brief hdd_wlan_startup() - HDD init function
7515
7516 This is the driver startup code executed once a WLAN device has been detected
7517
7518 \param - dev - Pointer to the underlying device
7519
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007520 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007521
7522 --------------------------------------------------------------------------*/
7523
7524int hdd_wlan_startup(struct device *dev )
7525{
7526 VOS_STATUS status;
7527 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007528 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007529 hdd_context_t *pHddCtx = NULL;
7530 v_CONTEXT_t pVosContext= NULL;
7531#ifdef WLAN_BTAMP_FEATURE
7532 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7533 WLANBAP_ConfigType btAmpConfig;
7534 hdd_config_t *pConfig;
7535#endif
7536 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007537 struct wiphy *wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007538
7539 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007540 /*
7541 * cfg80211: wiphy allocation
7542 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307543 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007544
7545 if(wiphy == NULL)
7546 {
7547 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007548 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007549 }
7550
7551 pHddCtx = wiphy_priv(wiphy);
7552
Jeff Johnson295189b2012-06-20 16:38:30 -07007553 //Initialize the adapter context to zeros.
7554 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7555
Jeff Johnson295189b2012-06-20 16:38:30 -07007556 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007557 hdd_prevent_suspend();
7558 pHddCtx->isLoadUnloadInProgress = TRUE;
7559
7560 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7561
7562 /*Get vos context here bcoz vos_open requires it*/
7563 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7564
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007565 if(pVosContext == NULL)
7566 {
7567 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7568 goto err_free_hdd_context;
7569 }
7570
Jeff Johnson295189b2012-06-20 16:38:30 -07007571 //Save the Global VOSS context in adapter context for future.
7572 pHddCtx->pvosContext = pVosContext;
7573
7574 //Save the adapter context in global context for future.
7575 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7576
Jeff Johnson295189b2012-06-20 16:38:30 -07007577 pHddCtx->parent_dev = dev;
7578
7579 init_completion(&pHddCtx->full_pwr_comp_var);
7580 init_completion(&pHddCtx->standby_comp_var);
7581 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007582 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007583 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307584 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007585
7586#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007587 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007588#else
7589 init_completion(&pHddCtx->driver_crda_req);
7590#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007591
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307592 spin_lock_init(&pHddCtx->schedScan_lock);
7593
Jeff Johnson295189b2012-06-20 16:38:30 -07007594 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7595
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307596#ifdef FEATURE_WLAN_TDLS
7597 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7598 * invoked by other instances also) to protect the concurrent
7599 * access for the Adapters by TDLS module.
7600 */
7601 mutex_init(&pHddCtx->tdls_lock);
7602#endif
7603
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307604 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007605 // Load all config first as TL config is needed during vos_open
7606 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7607 if(pHddCtx->cfg_ini == NULL)
7608 {
7609 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7610 goto err_free_hdd_context;
7611 }
7612
7613 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7614
7615 // Read and parse the qcom_cfg.ini file
7616 status = hdd_parse_config_ini( pHddCtx );
7617 if ( VOS_STATUS_SUCCESS != status )
7618 {
7619 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7620 __func__, WLAN_INI_FILE);
7621 goto err_config;
7622 }
Arif Hussaind5218912013-12-05 01:10:55 -08007623#ifdef MEMORY_DEBUG
7624 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
7625 vos_mem_init();
7626
7627 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
7628 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
7629#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007630
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307631 /* INI has been read, initialise the configuredMcastBcastFilter with
7632 * INI value as this will serve as the default value
7633 */
7634 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7635 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7636 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307637
7638 if (false == hdd_is_5g_supported(pHddCtx))
7639 {
7640 //5Ghz is not supported.
7641 if (1 != pHddCtx->cfg_ini->nBandCapability)
7642 {
7643 hddLog(VOS_TRACE_LEVEL_INFO,
7644 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7645 pHddCtx->cfg_ini->nBandCapability = 1;
7646 }
7647 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05307648
7649 /* If SNR Monitoring is enabled, FW has to parse all beacons
7650 * for calcaluting and storing the average SNR, so set Nth beacon
7651 * filter to 1 to enable FW to parse all the beaocons
7652 */
7653 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
7654 {
7655 /* The log level is deliberately set to WARN as overriding
7656 * nthBeaconFilter to 1 will increase power cosumption and this
7657 * might just prove helpful to detect the power issue.
7658 */
7659 hddLog(VOS_TRACE_LEVEL_WARN,
7660 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
7661 pHddCtx->cfg_ini->nthBeaconFilter = 1;
7662 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007663 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307664 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07007665 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307666 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
Jeff Johnson295189b2012-06-20 16:38:30 -07007667 {
7668 hddLog(VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307669 "%s: wlan_hdd_cfg80211_init return failure", __func__);
7670 goto err_config;
Jeff Johnson295189b2012-06-20 16:38:30 -07007671 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007672
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007673 // Update VOS trace levels based upon the cfg.ini
7674 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
7675 pHddCtx->cfg_ini->vosTraceEnableBAP);
7676 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
7677 pHddCtx->cfg_ini->vosTraceEnableTL);
7678 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
7679 pHddCtx->cfg_ini->vosTraceEnableWDI);
7680 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
7681 pHddCtx->cfg_ini->vosTraceEnableHDD);
7682 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
7683 pHddCtx->cfg_ini->vosTraceEnableSME);
7684 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
7685 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05307686 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
7687 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007688 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
7689 pHddCtx->cfg_ini->vosTraceEnableWDA);
7690 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
7691 pHddCtx->cfg_ini->vosTraceEnableSYS);
7692 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
7693 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007694 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
7695 pHddCtx->cfg_ini->vosTraceEnableSAP);
7696 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
7697 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08007698
Jeff Johnson295189b2012-06-20 16:38:30 -07007699 // Update WDI trace levels based upon the cfg.ini
7700 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
7701 pHddCtx->cfg_ini->wdiTraceEnableDAL);
7702 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
7703 pHddCtx->cfg_ini->wdiTraceEnableCTL);
7704 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
7705 pHddCtx->cfg_ini->wdiTraceEnableDAT);
7706 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
7707 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07007708
Jeff Johnson88ba7742013-02-27 14:36:02 -08007709 if (VOS_FTM_MODE == hdd_get_conparam())
7710 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007711 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
7712 {
7713 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
7714 goto err_free_hdd_context;
7715 }
7716 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
7717 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08007718 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007719
Jeff Johnson88ba7742013-02-27 14:36:02 -08007720 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07007721 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7722 {
7723 status = vos_watchdog_open(pVosContext,
7724 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
7725
7726 if(!VOS_IS_STATUS_SUCCESS( status ))
7727 {
7728 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307729 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007730 }
7731 }
7732
7733 pHddCtx->isLogpInProgress = FALSE;
7734 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
7735
Jeff Johnson295189b2012-06-20 16:38:30 -07007736 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
7737 if(!VOS_IS_STATUS_SUCCESS(status))
7738 {
7739 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007740 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007741 }
7742
Amar Singhala49cbc52013-10-08 18:37:44 -07007743#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07007744 /* initialize the NV module. This is required so that
7745 we can initialize the channel information in wiphy
7746 from the NV.bin data. The channel information in
7747 wiphy needs to be initialized before wiphy registration */
7748
7749 status = vos_nv_open();
7750 if (!VOS_IS_STATUS_SUCCESS(status))
7751 {
7752 /* NV module cannot be initialized */
7753 hddLog( VOS_TRACE_LEVEL_FATAL,
7754 "%s: vos_nv_open failed", __func__);
7755 goto err_clkvote;
7756 }
7757
7758 status = vos_init_wiphy_from_nv_bin();
7759 if (!VOS_IS_STATUS_SUCCESS(status))
7760 {
7761 /* NV module cannot be initialized */
7762 hddLog( VOS_TRACE_LEVEL_FATAL,
7763 "%s: vos_init_wiphy failed", __func__);
7764 goto err_vos_nv_close;
7765 }
7766
Amar Singhala49cbc52013-10-08 18:37:44 -07007767 /* registration of wiphy dev with cfg80211 */
7768 if (0 > wlan_hdd_cfg80211_register(wiphy))
7769 {
7770 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
Amar Singhal0a402232013-10-11 20:57:16 -07007771 goto err_vos_nv_close;
Amar Singhala49cbc52013-10-08 18:37:44 -07007772 }
7773#endif
7774
Jeff Johnson295189b2012-06-20 16:38:30 -07007775 status = vos_open( &pVosContext, 0);
7776 if ( !VOS_IS_STATUS_SUCCESS( status ))
7777 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007778 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Amar Singhala49cbc52013-10-08 18:37:44 -07007779 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07007780 }
7781
Jeff Johnson295189b2012-06-20 16:38:30 -07007782 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
7783
7784 if ( NULL == pHddCtx->hHal )
7785 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007786 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007787 goto err_vosclose;
7788 }
7789
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007790 status = vos_preStart( pHddCtx->pvosContext );
7791 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7792 {
7793 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
7794 goto err_vosclose;
7795 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007796
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007797 /* Note that the vos_preStart() sequence triggers the cfg download.
7798 The cfg download must occur before we update the SME config
7799 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07007800 status = hdd_set_sme_config( pHddCtx );
7801
7802 if ( VOS_STATUS_SUCCESS != status )
7803 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007804 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
7805 goto err_vosclose;
7806 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007807
7808 //Initialize the WMM module
7809 status = hdd_wmm_init(pHddCtx);
7810 if (!VOS_IS_STATUS_SUCCESS(status))
7811 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007812 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007813 goto err_vosclose;
7814 }
7815
Jeff Johnson295189b2012-06-20 16:38:30 -07007816 /* In the integrated architecture we update the configuration from
7817 the INI file and from NV before vOSS has been started so that
7818 the final contents are available to send down to the cCPU */
7819
Arif Hussain66559122013-11-21 10:11:40 -08007820 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
7821 {
7822 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
7823 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
7824 __func__, enable_dfs_chan_scan);
7825 }
7826 if (0 == enable_11d || 1 == enable_11d)
7827 {
7828 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
7829 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
7830 __func__, enable_11d);
7831 }
7832
Jeff Johnson295189b2012-06-20 16:38:30 -07007833 // Apply the cfg.ini to cfg.dat
7834 if (FALSE == hdd_update_config_dat(pHddCtx))
7835 {
7836 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
7837 goto err_vosclose;
7838 }
7839
7840 // Apply the NV to cfg.dat
7841 /* Prima Update MAC address only at here */
7842 if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
7843 {
7844#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
7845 /* There was not a valid set of MAC Addresses in NV. See if the
7846 default addresses were modified by the cfg.ini settings. If so,
7847 we'll use them, but if not, we'll autogenerate a set of MAC
7848 addresses based upon the device serial number */
7849
7850 static const v_MACADDR_t default_address =
7851 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
7852 unsigned int serialno;
7853 int i;
7854
7855 serialno = wcnss_get_serial_number();
7856 if ((0 != serialno) &&
7857 (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
7858 sizeof(default_address))))
7859 {
7860 /* cfg.ini has the default address, invoke autogen logic */
7861
7862 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7863 bytes of the serial number that can be used to generate
7864 the other 3 bytes of the MAC address. Mask off all but
7865 the lower 3 bytes (this will also make sure we don't
7866 overflow in the next step) */
7867 serialno &= 0x00FFFFFF;
7868
7869 /* we need a unique address for each session */
7870 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7871
7872 /* autogen all addresses */
7873 for (i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7874 {
7875 /* start with the entire default address */
7876 pHddCtx->cfg_ini->intfMacAddr[i] = default_address;
7877 /* then replace the lower 3 bytes */
7878 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7879 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7880 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7881
7882 serialno++;
7883 }
7884
7885 pr_info("wlan: Invalid MAC addresses in NV, autogenerated "
7886 MAC_ADDRESS_STR,
7887 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7888 }
7889 else
7890#endif //WLAN_AUTOGEN_MACADDR_FEATURE
7891 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007892 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007893 "%s: Invalid MAC address in NV, using MAC from ini file "
7894 MAC_ADDRESS_STR, __func__,
7895 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
7896 }
7897 }
7898 {
7899 eHalStatus halStatus;
7900 // Set the MAC Address
7901 // Currently this is used by HAL to add self sta. Remove this once self sta is added as part of session open.
7902 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
7903 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
7904 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
7905
7906 if (!HAL_STATUS_SUCCESS( halStatus ))
7907 {
7908 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
7909 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Madan Mohan Koyyalamudib8b126b2012-11-15 17:37:30 -08007910 goto err_vosclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07007911 }
7912 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007913
7914 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
7915 Note: Firmware image will be read and downloaded inside vos_start API */
7916 status = vos_start( pHddCtx->pvosContext );
7917 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7918 {
7919 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
7920 goto err_vosclose;
7921 }
7922
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007923 /* Exchange capability info between Host and FW and also get versioning info from FW */
7924 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007925
7926 status = hdd_post_voss_start_config( pHddCtx );
7927 if ( !VOS_IS_STATUS_SUCCESS( status ) )
7928 {
7929 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
7930 __func__);
7931 goto err_vosstop;
7932 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007933
7934#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307935 wlan_hdd_cfg80211_update_reg_info( wiphy );
7936
7937 /* registration of wiphy dev with cfg80211 */
7938 if (0 > wlan_hdd_cfg80211_register(wiphy))
7939 {
7940 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
7941 goto err_vosstop;
7942 }
Amar Singhala49cbc52013-10-08 18:37:44 -07007943#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007944
Jeff Johnson295189b2012-06-20 16:38:30 -07007945 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7946 {
7947 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
7948 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7949 }
7950 else
7951 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007952 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
7953 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
7954 if (pAdapter != NULL)
7955 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307956 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07007957 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307958 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
7959 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
7960 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07007961
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307962 /* Generate the P2P Device Address. This consists of the device's
7963 * primary MAC address with the locally administered bit set.
7964 */
7965 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07007966 }
7967 else
7968 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05307969 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
7970 if (p2p_dev_addr != NULL)
7971 {
7972 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
7973 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
7974 }
7975 else
7976 {
7977 hddLog(VOS_TRACE_LEVEL_FATAL,
7978 "%s: Failed to allocate mac_address for p2p_device",
7979 __func__);
7980 goto err_close_adapter;
7981 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007982 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007983
7984 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
7985 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
7986 if ( NULL == pP2pAdapter )
7987 {
7988 hddLog(VOS_TRACE_LEVEL_FATAL,
7989 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007990 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07007991 goto err_close_adapter;
7992 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007993 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007994 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007995
7996 if( pAdapter == NULL )
7997 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08007998 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
7999 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008000 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008001
Arif Hussain66559122013-11-21 10:11:40 -08008002 if (country_code)
8003 {
8004 eHalStatus ret;
8005 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8006#ifndef CONFIG_ENABLE_LINUX_REG
8007 hdd_checkandupdate_phymode(pAdapter, country_code);
8008#endif
8009 ret = sme_ChangeCountryCode(pHddCtx->hHal, NULL,
8010 country_code,
8011 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308012 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008013 if (eHAL_STATUS_SUCCESS == ret)
8014 {
8015 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8016 "%s: SME Change Country code from module param fail ret=%d",
8017 __func__, ret);
8018 }
8019 else
8020 {
8021 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module country code set to %c%c",
8022 __func__, country_code[0], country_code[1]);
8023 }
8024 }
8025
Jeff Johnson295189b2012-06-20 16:38:30 -07008026#ifdef WLAN_BTAMP_FEATURE
8027 vStatus = WLANBAP_Open(pVosContext);
8028 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8029 {
8030 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8031 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008032 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008033 }
8034
8035 vStatus = BSL_Init(pVosContext);
8036 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8037 {
8038 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8039 "%s: Failed to Init BSL",__func__);
8040 goto err_bap_close;
8041 }
8042 vStatus = WLANBAP_Start(pVosContext);
8043 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8044 {
8045 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8046 "%s: Failed to start TL",__func__);
8047 goto err_bap_close;
8048 }
8049
8050 pConfig = pHddCtx->cfg_ini;
8051 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8052 status = WLANBAP_SetConfig(&btAmpConfig);
8053
8054#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008055
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008056#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8057 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8058 {
8059 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8060 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8061 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8062 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8063 }
8064#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008065#ifdef FEATURE_WLAN_SCAN_PNO
8066 /*SME must send channel update configuration to RIVA*/
8067 sme_UpdateChannelConfig(pHddCtx->hHal);
8068#endif
8069
Jeff Johnson295189b2012-06-20 16:38:30 -07008070 /* Register with platform driver as client for Suspend/Resume */
8071 status = hddRegisterPmOps(pHddCtx);
8072 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8073 {
8074 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8075#ifdef WLAN_BTAMP_FEATURE
8076 goto err_bap_stop;
8077#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008078 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008079#endif //WLAN_BTAMP_FEATURE
8080 }
8081
Yue Ma0d4891e2013-08-06 17:01:45 -07008082 /* Open debugfs interface */
8083 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8084 {
8085 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8086 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008087 }
8088
Jeff Johnson295189b2012-06-20 16:38:30 -07008089 /* Register TM level change handler function to the platform */
8090 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8091 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8092 {
8093 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8094 goto err_unregister_pmops;
8095 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008096
8097 /* register for riva power on lock to platform driver */
8098 if (req_riva_power_on_lock("wlan"))
8099 {
8100 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8101 __func__);
8102 goto err_unregister_pmops;
8103 }
8104
Jeff Johnson295189b2012-06-20 16:38:30 -07008105 // register net device notifier for device change notification
8106 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8107
8108 if(ret < 0)
8109 {
8110 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8111 goto err_free_power_on_lock;
8112 }
8113
8114 //Initialize the nlink service
8115 if(nl_srv_init() != 0)
8116 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308117 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008118 goto err_reg_netdev;
8119 }
8120
Leo Chang4ce1cc52013-10-21 18:27:15 -07008121#ifdef WLAN_KD_READY_NOTIFIER
8122 pHddCtx->kd_nl_init = 1;
8123#endif /* WLAN_KD_READY_NOTIFIER */
8124
Jeff Johnson295189b2012-06-20 16:38:30 -07008125 //Initialize the BTC service
8126 if(btc_activate_service(pHddCtx) != 0)
8127 {
8128 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8129 goto err_nl_srv;
8130 }
8131
8132#ifdef PTT_SOCK_SVC_ENABLE
8133 //Initialize the PTT service
8134 if(ptt_sock_activate_svc(pHddCtx) != 0)
8135 {
8136 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8137 goto err_nl_srv;
8138 }
8139#endif
8140
Jeff Johnson295189b2012-06-20 16:38:30 -07008141 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008142 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008143 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008144 /* Action frame registered in one adapter which will
8145 * applicable to all interfaces
8146 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008147 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008148 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008149
8150 mutex_init(&pHddCtx->sap_lock);
8151
8152 pHddCtx->isLoadUnloadInProgress = FALSE;
8153
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008154#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008155#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8156 /* Initialize the wake lcok */
8157 wake_lock_init(&pHddCtx->rx_wake_lock,
8158 WAKE_LOCK_SUSPEND,
8159 "qcom_rx_wakelock");
8160#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008161 /* Initialize the wake lcok */
8162 wake_lock_init(&pHddCtx->sap_wake_lock,
8163 WAKE_LOCK_SUSPEND,
8164 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008165#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008166
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008167 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8168 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008169
8170 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8171 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308172#ifndef CONFIG_ENABLE_LINUX_REG
8173 /*updating wiphy so that regulatory user hints can be processed*/
8174 if (wiphy)
8175 {
8176 regulatory_hint(wiphy, "00");
8177 }
8178#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008179 // Initialize the restart logic
8180 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308181
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008182 //Register the traffic monitor timer now
8183 if ( pHddCtx->cfg_ini->dynSplitscan)
8184 {
8185 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8186 VOS_TIMER_TYPE_SW,
8187 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8188 (void *)pHddCtx);
8189 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008190 goto success;
8191
8192err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008193#ifdef WLAN_KD_READY_NOTIFIER
8194 nl_srv_exit(pHddCtx->ptt_pid);
8195#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008196 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008197#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008198err_reg_netdev:
8199 unregister_netdevice_notifier(&hdd_netdev_notifier);
8200
8201err_free_power_on_lock:
8202 free_riva_power_on_lock("wlan");
8203
8204err_unregister_pmops:
8205 hddDevTmUnregisterNotifyCallback(pHddCtx);
8206 hddDeregisterPmOps(pHddCtx);
8207
Yue Ma0d4891e2013-08-06 17:01:45 -07008208 hdd_debugfs_exit(pHddCtx);
8209
Jeff Johnson295189b2012-06-20 16:38:30 -07008210#ifdef WLAN_BTAMP_FEATURE
8211err_bap_stop:
8212 WLANBAP_Stop(pVosContext);
8213#endif
8214
8215#ifdef WLAN_BTAMP_FEATURE
8216err_bap_close:
8217 WLANBAP_Close(pVosContext);
8218#endif
8219
Jeff Johnson295189b2012-06-20 16:38:30 -07008220err_close_adapter:
8221 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008222
8223#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308224 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008225#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008226
8227err_vosstop:
8228 vos_stop(pVosContext);
8229
Amar Singhala49cbc52013-10-08 18:37:44 -07008230err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008231 status = vos_sched_close( pVosContext );
8232 if (!VOS_IS_STATUS_SUCCESS(status)) {
8233 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8234 "%s: Failed to close VOSS Scheduler", __func__);
8235 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8236 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008237 vos_close(pVosContext );
8238
8239err_wiphy_unregister:
8240
8241#ifdef CONFIG_ENABLE_LINUX_REG
8242 wiphy_unregister(wiphy);
Jeff Johnson295189b2012-06-20 16:38:30 -07008243
Amar Singhal0a402232013-10-11 20:57:16 -07008244err_vos_nv_close:
8245
8246 vos_nv_close();
8247
Jeff Johnson295189b2012-06-20 16:38:30 -07008248err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008249#endif
8250
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008251 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008252
8253err_wdclose:
8254 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8255 vos_watchdog_close(pVosContext);
8256
Jeff Johnson295189b2012-06-20 16:38:30 -07008257err_config:
8258 kfree(pHddCtx->cfg_ini);
8259 pHddCtx->cfg_ini= NULL;
8260
8261err_free_hdd_context:
8262 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008263 wiphy_free(wiphy) ;
8264 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008265 VOS_BUG(1);
8266
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008267 if (hdd_is_ssr_required())
8268 {
8269 /* WDI timeout had happened during load, so SSR is needed here */
8270 subsystem_restart("wcnss");
8271 msleep(5000);
8272 }
8273 hdd_set_ssr_required (VOS_FALSE);
8274
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008275 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008276
8277success:
8278 EXIT();
8279 return 0;
8280}
8281
8282/**---------------------------------------------------------------------------
8283
Jeff Johnson32d95a32012-09-10 13:15:23 -07008284 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008285
Jeff Johnson32d95a32012-09-10 13:15:23 -07008286 This is the driver entry point - called in different timeline depending
8287 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008288
8289 \param - None
8290
8291 \return - 0 for success, non zero for failure
8292
8293 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008294static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008295{
8296 VOS_STATUS status;
8297 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008298 struct device *dev = NULL;
8299 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008300#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8301 int max_retries = 0;
8302#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008303
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308304#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8305 vos_wconn_trace_init();
8306#endif
8307
Jeff Johnson295189b2012-06-20 16:38:30 -07008308 ENTER();
8309
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008310#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008311 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008312#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008313
8314 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8315 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8316
8317 //Power Up Libra WLAN card first if not already powered up
8318 status = vos_chipPowerUp(NULL,NULL,NULL);
8319 if (!VOS_IS_STATUS_SUCCESS(status))
8320 {
8321 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8322 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308323#ifdef WLAN_OPEN_SOURCE
8324 wake_lock_destroy(&wlan_wake_lock);
8325#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008326 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008327 }
8328
Jeff Johnson295189b2012-06-20 16:38:30 -07008329#ifdef ANI_BUS_TYPE_PCI
8330
8331 dev = wcnss_wlan_get_device();
8332
8333#endif // ANI_BUS_TYPE_PCI
8334
8335#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008336
8337#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8338 /* wait until WCNSS driver downloads NV */
8339 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8340 msleep(1000);
8341 }
8342 if (max_retries >= 5) {
8343 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308344#ifdef WLAN_OPEN_SOURCE
8345 wake_lock_destroy(&wlan_wake_lock);
8346#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008347 return -ENODEV;
8348 }
8349#endif
8350
Jeff Johnson295189b2012-06-20 16:38:30 -07008351 dev = wcnss_wlan_get_device();
8352#endif // ANI_BUS_TYPE_PLATFORM
8353
8354
8355 do {
8356 if (NULL == dev) {
8357 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8358 ret_status = -1;
8359 break;
8360 }
8361
Jeff Johnson295189b2012-06-20 16:38:30 -07008362#ifdef TIMER_MANAGER
8363 vos_timer_manager_init();
8364#endif
8365
8366 /* Preopen VOSS so that it is ready to start at least SAL */
8367 status = vos_preOpen(&pVosContext);
8368
8369 if (!VOS_IS_STATUS_SUCCESS(status))
8370 {
8371 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8372 ret_status = -1;
8373 break;
8374 }
8375
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008376#ifndef MODULE
8377 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8378 */
8379 hdd_set_conparam((v_UINT_t)con_mode);
8380#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008381
8382 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008383 if (hdd_wlan_startup(dev))
8384 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008385 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008386 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008387 vos_preClose( &pVosContext );
8388 ret_status = -1;
8389 break;
8390 }
8391
8392 /* Cancel the vote for XO Core ON
8393 * This is done here for safety purposes in case we re-initialize without turning
8394 * it OFF in any error scenario.
8395 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008396 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008397 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008398 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008399 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8400 {
8401 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008402 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008403 }
8404 } while (0);
8405
8406 if (0 != ret_status)
8407 {
8408 //Assert Deep sleep signal now to put Libra HW in lowest power state
8409 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8410 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8411
8412 //Vote off any PMIC voltage supplies
8413 vos_chipPowerDown(NULL, NULL, NULL);
8414#ifdef TIMER_MANAGER
8415 vos_timer_exit();
8416#endif
8417#ifdef MEMORY_DEBUG
8418 vos_mem_exit();
8419#endif
8420
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008421#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008422 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008423#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008424 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8425 }
8426 else
8427 {
8428 //Send WLAN UP indication to Nlink Service
8429 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8430
8431 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008432 }
8433
8434 EXIT();
8435
8436 return ret_status;
8437}
8438
Jeff Johnson32d95a32012-09-10 13:15:23 -07008439/**---------------------------------------------------------------------------
8440
8441 \brief hdd_module_init() - Init Function
8442
8443 This is the driver entry point (invoked when module is loaded using insmod)
8444
8445 \param - None
8446
8447 \return - 0 for success, non zero for failure
8448
8449 --------------------------------------------------------------------------*/
8450#ifdef MODULE
8451static int __init hdd_module_init ( void)
8452{
8453 return hdd_driver_init();
8454}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008455#else /* #ifdef MODULE */
8456static int __init hdd_module_init ( void)
8457{
8458 /* Driver initialization is delayed to fwpath_changed_handler */
8459 return 0;
8460}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008461#endif /* #ifdef MODULE */
8462
Jeff Johnson295189b2012-06-20 16:38:30 -07008463
8464/**---------------------------------------------------------------------------
8465
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008466 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008467
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008468 This is the driver exit point (invoked when module is unloaded using rmmod
8469 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008470
8471 \param - None
8472
8473 \return - None
8474
8475 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008476static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008477{
8478 hdd_context_t *pHddCtx = NULL;
8479 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008480 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008481
8482 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8483
8484 //Get the global vos context
8485 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8486
8487 if(!pVosContext)
8488 {
8489 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8490 goto done;
8491 }
8492
8493 //Get the HDD context.
8494 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8495
8496 if(!pHddCtx)
8497 {
8498 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8499 }
8500 else
8501 {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008502 while(isWDresetInProgress()) {
8503 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8504 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008505 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008506
8507 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8508 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8509 "%s:SSR never completed, fatal error", __func__);
8510 VOS_BUG(0);
8511 }
8512 }
8513
Jeff Johnson295189b2012-06-20 16:38:30 -07008514
8515 pHddCtx->isLoadUnloadInProgress = TRUE;
8516 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8517
8518 //Do all the cleanup before deregistering the driver
8519 hdd_wlan_exit(pHddCtx);
8520 }
8521
Jeff Johnson295189b2012-06-20 16:38:30 -07008522 vos_preClose( &pVosContext );
8523
8524#ifdef TIMER_MANAGER
8525 vos_timer_exit();
8526#endif
8527#ifdef MEMORY_DEBUG
8528 vos_mem_exit();
8529#endif
8530
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308531#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8532 vos_wconn_trace_exit();
8533#endif
8534
Jeff Johnson295189b2012-06-20 16:38:30 -07008535done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008536#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008537 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008538#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008539 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8540}
8541
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008542/**---------------------------------------------------------------------------
8543
8544 \brief hdd_module_exit() - Exit function
8545
8546 This is the driver exit point (invoked when module is unloaded using rmmod)
8547
8548 \param - None
8549
8550 \return - None
8551
8552 --------------------------------------------------------------------------*/
8553static void __exit hdd_module_exit(void)
8554{
8555 hdd_driver_exit();
8556}
8557
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008558#ifdef MODULE
8559static int fwpath_changed_handler(const char *kmessage,
8560 struct kernel_param *kp)
8561{
Jeff Johnson76052702013-04-16 13:55:05 -07008562 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008563}
8564
8565static int con_mode_handler(const char *kmessage,
8566 struct kernel_param *kp)
8567{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008568 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008569}
8570#else /* #ifdef MODULE */
8571/**---------------------------------------------------------------------------
8572
Jeff Johnson76052702013-04-16 13:55:05 -07008573 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008574
Jeff Johnson76052702013-04-16 13:55:05 -07008575 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008576 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008577 - invoked when module parameter fwpath is modified from userspace to signal
8578 initializing the WLAN driver or when con_mode is modified from userspace
8579 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008580
8581 \return - 0 for success, non zero for failure
8582
8583 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008584static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008585{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008586 int ret_status;
8587
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008588 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008589 ret_status = hdd_driver_init();
8590 wlan_hdd_inited = ret_status ? 0 : 1;
8591 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008592 }
8593
8594 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008595
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008596 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008597
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008598 ret_status = hdd_driver_init();
8599 wlan_hdd_inited = ret_status ? 0 : 1;
8600 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008601}
8602
Jeff Johnson295189b2012-06-20 16:38:30 -07008603/**---------------------------------------------------------------------------
8604
Jeff Johnson76052702013-04-16 13:55:05 -07008605 \brief fwpath_changed_handler() - Handler Function
8606
8607 Handle changes to the fwpath parameter
8608
8609 \return - 0 for success, non zero for failure
8610
8611 --------------------------------------------------------------------------*/
8612static int fwpath_changed_handler(const char *kmessage,
8613 struct kernel_param *kp)
8614{
8615 int ret;
8616
8617 ret = param_set_copystring(kmessage, kp);
8618 if (0 == ret)
8619 ret = kickstart_driver();
8620 return ret;
8621}
8622
8623/**---------------------------------------------------------------------------
8624
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008625 \brief con_mode_handler() -
8626
8627 Handler function for module param con_mode when it is changed by userspace
8628 Dynamically linked - do nothing
8629 Statically linked - exit and init driver, as in rmmod and insmod
8630
Jeff Johnson76052702013-04-16 13:55:05 -07008631 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008632
Jeff Johnson76052702013-04-16 13:55:05 -07008633 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008634
8635 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008636static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008637{
Jeff Johnson76052702013-04-16 13:55:05 -07008638 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008639
Jeff Johnson76052702013-04-16 13:55:05 -07008640 ret = param_set_int(kmessage, kp);
8641 if (0 == ret)
8642 ret = kickstart_driver();
8643 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008644}
8645#endif /* #ifdef MODULE */
8646
8647/**---------------------------------------------------------------------------
8648
Jeff Johnson295189b2012-06-20 16:38:30 -07008649 \brief hdd_get_conparam() -
8650
8651 This is the driver exit point (invoked when module is unloaded using rmmod)
8652
8653 \param - None
8654
8655 \return - tVOS_CON_MODE
8656
8657 --------------------------------------------------------------------------*/
8658tVOS_CON_MODE hdd_get_conparam ( void )
8659{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008660#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07008661 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008662#else
8663 return (tVOS_CON_MODE)curr_con_mode;
8664#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008665}
8666void hdd_set_conparam ( v_UINT_t newParam )
8667{
8668 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008669#ifndef MODULE
8670 curr_con_mode = con_mode;
8671#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008672}
8673/**---------------------------------------------------------------------------
8674
8675 \brief hdd_softap_sta_deauth() - function
8676
8677 This to take counter measure to handle deauth req from HDD
8678
8679 \param - pAdapter - Pointer to the HDD
8680
8681 \param - enable - boolean value
8682
8683 \return - None
8684
8685 --------------------------------------------------------------------------*/
8686
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008687VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07008688{
Jeff Johnson295189b2012-06-20 16:38:30 -07008689 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008690 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07008691
8692 ENTER();
8693
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07008694 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
8695 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008696
8697 //Ignore request to deauth bcmc station
8698 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008699 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008700
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008701 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07008702
8703 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08008704 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07008705}
8706
8707/**---------------------------------------------------------------------------
8708
8709 \brief hdd_softap_sta_disassoc() - function
8710
8711 This to take counter measure to handle deauth req from HDD
8712
8713 \param - pAdapter - Pointer to the HDD
8714
8715 \param - enable - boolean value
8716
8717 \return - None
8718
8719 --------------------------------------------------------------------------*/
8720
8721void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
8722{
8723 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8724
8725 ENTER();
8726
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308727 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008728
8729 //Ignore request to disassoc bcmc station
8730 if( pDestMacAddress[0] & 0x1 )
8731 return;
8732
8733 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
8734}
8735
8736void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
8737{
8738 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
8739
8740 ENTER();
8741
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308742 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07008743
8744 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
8745}
8746
Jeff Johnson295189b2012-06-20 16:38:30 -07008747/**---------------------------------------------------------------------------
8748 *
8749 * \brief hdd_get__concurrency_mode() -
8750 *
8751 *
8752 * \param - None
8753 *
8754 * \return - CONCURRENCY MODE
8755 *
8756 * --------------------------------------------------------------------------*/
8757tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
8758{
8759 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
8760 hdd_context_t *pHddCtx;
8761
8762 if (NULL != pVosContext)
8763 {
8764 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
8765 if (NULL != pHddCtx)
8766 {
8767 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
8768 }
8769 }
8770
8771 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008772 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008773 return VOS_STA;
8774}
8775
8776/* Decide whether to allow/not the apps power collapse.
8777 * Allow apps power collapse if we are in connected state.
8778 * if not, allow only if we are in IMPS */
8779v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
8780{
8781 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08008782 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008783 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07008784 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8785 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
8786 hdd_adapter_t *pAdapter = NULL;
8787 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08008788 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008789
Jeff Johnson295189b2012-06-20 16:38:30 -07008790 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8791 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07008792
Yathish9f22e662012-12-10 14:21:35 -08008793 concurrent_state = hdd_get_concurrency_mode();
8794
8795#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
8796 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
8797 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
8798 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
8799 return TRUE;
8800#endif
8801
Jeff Johnson295189b2012-06-20 16:38:30 -07008802 /*loop through all adapters. TBD fix for Concurrency */
8803 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8804 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
8805 {
8806 pAdapter = pAdapterNode->pAdapter;
8807 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
8808 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
8809 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008810 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07008811 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08008812 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008813 (eANI_BOOLEAN_TRUE == scanRspPending) ||
8814 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07008815 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08008816 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08008817 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
8818 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07008819 return FALSE;
8820 }
8821 }
8822 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8823 pAdapterNode = pNext;
8824 }
8825 return TRUE;
8826}
8827
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08008828/* Decides whether to send suspend notification to Riva
8829 * if any adapter is in BMPS; then it is required */
8830v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
8831{
8832 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
8833 hdd_config_t *pConfig = pHddCtx->cfg_ini;
8834
8835 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
8836 {
8837 return TRUE;
8838 }
8839 return FALSE;
8840}
8841
Jeff Johnson295189b2012-06-20 16:38:30 -07008842void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8843{
8844 switch(mode)
8845 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008846 case VOS_STA_MODE:
8847 case VOS_P2P_CLIENT_MODE:
8848 case VOS_P2P_GO_MODE:
8849 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07008850 pHddCtx->concurrency_mode |= (1 << mode);
8851 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07008852 break;
8853 default:
8854 break;
8855
8856 }
8857 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8858 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8859}
8860
8861
8862void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
8863{
8864 switch(mode)
8865 {
Chilam Ngc4244af2013-04-01 15:37:32 -07008866 case VOS_STA_MODE:
8867 case VOS_P2P_CLIENT_MODE:
8868 case VOS_P2P_GO_MODE:
8869 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07008870 pHddCtx->no_of_sessions[mode]--;
8871 if (!(pHddCtx->no_of_sessions[mode]))
8872 pHddCtx->concurrency_mode &= (~(1 << mode));
8873 break;
8874 default:
8875 break;
8876 }
8877 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
8878 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
8879}
8880
Jeff Johnsone7245742012-09-05 17:12:55 -07008881/**---------------------------------------------------------------------------
8882 *
8883 * \brief wlan_hdd_restart_init
8884 *
8885 * This function initalizes restart timer/flag. An internal function.
8886 *
8887 * \param - pHddCtx
8888 *
8889 * \return - None
8890 *
8891 * --------------------------------------------------------------------------*/
8892
8893static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
8894{
8895 /* Initialize */
8896 pHddCtx->hdd_restart_retries = 0;
8897 atomic_set(&pHddCtx->isRestartInProgress, 0);
8898 vos_timer_init(&pHddCtx->hdd_restart_timer,
8899 VOS_TIMER_TYPE_SW,
8900 wlan_hdd_restart_timer_cb,
8901 pHddCtx);
8902}
8903/**---------------------------------------------------------------------------
8904 *
8905 * \brief wlan_hdd_restart_deinit
8906 *
8907 * This function cleans up the resources used. An internal function.
8908 *
8909 * \param - pHddCtx
8910 *
8911 * \return - None
8912 *
8913 * --------------------------------------------------------------------------*/
8914
8915static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
8916{
8917
8918 VOS_STATUS vos_status;
8919 /* Block any further calls */
8920 atomic_set(&pHddCtx->isRestartInProgress, 1);
8921 /* Cleanup */
8922 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
8923 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008924 hddLog(LOGW, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008925 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
8926 if (!VOS_IS_STATUS_SUCCESS(vos_status))
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008927 hddLog(LOGW, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07008928
8929}
8930
8931/**---------------------------------------------------------------------------
8932 *
8933 * \brief wlan_hdd_framework_restart
8934 *
8935 * This function uses a cfg80211 API to start a framework initiated WLAN
8936 * driver module unload/load.
8937 *
8938 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
8939 *
8940 *
8941 * \param - pHddCtx
8942 *
8943 * \return - VOS_STATUS_SUCCESS: Success
8944 * VOS_STATUS_E_EMPTY: Adapter is Empty
8945 * VOS_STATUS_E_NOMEM: No memory
8946
8947 * --------------------------------------------------------------------------*/
8948
8949static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
8950{
8951 VOS_STATUS status = VOS_STATUS_SUCCESS;
8952 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008953 int len = (sizeof (struct ieee80211_mgmt));
8954 struct ieee80211_mgmt *mgmt = NULL;
8955
8956 /* Prepare the DEAUTH managment frame with reason code */
8957 mgmt = kzalloc(len, GFP_KERNEL);
8958 if(mgmt == NULL)
8959 {
8960 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8961 "%s: memory allocation failed (%d bytes)", __func__, len);
8962 return VOS_STATUS_E_NOMEM;
8963 }
8964 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07008965
8966 /* Iterate over all adapters/devices */
8967 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
8968 do
8969 {
8970 if( (status == VOS_STATUS_SUCCESS) &&
8971 pAdapterNode &&
8972 pAdapterNode->pAdapter)
8973 {
8974 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8975 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
8976 pAdapterNode->pAdapter->dev->name,
8977 pAdapterNode->pAdapter->device_mode,
8978 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008979 /*
8980 * CFG80211 event to restart the driver
8981 *
8982 * 'cfg80211_send_unprot_deauth' sends a
8983 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
8984 * of SME(Linux Kernel) state machine.
8985 *
8986 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
8987 * the driver.
8988 *
8989 */
8990
8991 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07008992 }
8993 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
8994 pAdapterNode = pNext;
8995 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
8996
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07008997
8998 /* Free the allocated management frame */
8999 kfree(mgmt);
9000
Jeff Johnsone7245742012-09-05 17:12:55 -07009001 /* Retry until we unload or reach max count */
9002 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9003 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9004
9005 return status;
9006
9007}
9008/**---------------------------------------------------------------------------
9009 *
9010 * \brief wlan_hdd_restart_timer_cb
9011 *
9012 * Restart timer callback. An internal function.
9013 *
9014 * \param - User data:
9015 *
9016 * \return - None
9017 *
9018 * --------------------------------------------------------------------------*/
9019
9020void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9021{
9022 hdd_context_t *pHddCtx = usrDataForCallback;
9023 wlan_hdd_framework_restart(pHddCtx);
9024 return;
9025
9026}
9027
9028
9029/**---------------------------------------------------------------------------
9030 *
9031 * \brief wlan_hdd_restart_driver
9032 *
9033 * This function sends an event to supplicant to restart the WLAN driver.
9034 *
9035 * This function is called from vos_wlanRestart.
9036 *
9037 * \param - pHddCtx
9038 *
9039 * \return - VOS_STATUS_SUCCESS: Success
9040 * VOS_STATUS_E_EMPTY: Adapter is Empty
9041 * VOS_STATUS_E_ALREADY: Request already in progress
9042
9043 * --------------------------------------------------------------------------*/
9044VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9045{
9046 VOS_STATUS status = VOS_STATUS_SUCCESS;
9047
9048 /* A tight check to make sure reentrancy */
9049 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9050 {
9051 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9052 "%s: WLAN restart is already in progress", __func__);
9053
9054 return VOS_STATUS_E_ALREADY;
9055 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009056 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009057#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009058 wcnss_reset_intr();
9059#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009060
Jeff Johnsone7245742012-09-05 17:12:55 -07009061 return status;
9062}
9063
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009064/*
9065 * API to find if there is any STA or P2P-Client is connected
9066 */
9067VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9068{
9069 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9070}
Jeff Johnsone7245742012-09-05 17:12:55 -07009071
Jeff Johnson295189b2012-06-20 16:38:30 -07009072//Register the module init/exit functions
9073module_init(hdd_module_init);
9074module_exit(hdd_module_exit);
9075
9076MODULE_LICENSE("Dual BSD/GPL");
9077MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9078MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9079
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009080module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9081 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009082
Jeff Johnson76052702013-04-16 13:55:05 -07009083module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009084 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009085
9086module_param(enable_dfs_chan_scan, int,
9087 S_IRUSR | S_IRGRP | S_IROTH);
9088
9089module_param(enable_11d, int,
9090 S_IRUSR | S_IRGRP | S_IROTH);
9091
9092module_param(country_code, charp,
9093 S_IRUSR | S_IRGRP | S_IROTH);