blob: d9184e1f0d9a21bcb6798d537c411d55ad928a92 [file] [log] [blame]
Jeff Johnson295189b2012-06-20 16:38:30 -07001/*
Kiet Lam842dad02014-02-18 18:44:02 -08002 * Copyright (c) 2012-2014 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
22/*
Kiet Lamaa8e15a2014-02-11 23:30:06 -080023 * Copyright (c) 2012-2014 Qualcomm Atheros, Inc.
24 * All Rights Reserved.
25 * Qualcomm Atheros Confidential and Proprietary.
Kiet Lam842dad02014-02-18 18:44:02 -080026 *
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080027 */
Kiet Lam842dad02014-02-18 18:44:02 -080028
29
Jeff Johnson295189b2012-06-20 16:38:30 -070030/*========================================================================
31
32 \file wlan_hdd_main.c
33
34 \brief WLAN Host Device Driver implementation
35
36 Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved.
37
38 Qualcomm Confidential and Proprietary.
39
40 ========================================================================*/
41
42/**=========================================================================
43
44 EDIT HISTORY FOR FILE
45
46
47 This section contains comments describing changes made to the module.
48 Notice that changes are listed in reverse chronological order.
49
50
51 $Header:$ $DateTime: $ $Author: $
52
53
54 when who what, where, why
55 -------- --- --------------------------------------------------------
56 04/5/09 Shailender Created module.
57 02/24/10 Sudhir.S.Kohalli Added to support param for SoftAP module
58 06/03/10 js - Added support to hostapd driven deauth/disassoc/mic failure
59 ==========================================================================*/
60
61/*--------------------------------------------------------------------------
62 Include Files
63 ------------------------------------------------------------------------*/
64//#include <wlan_qct_driver.h>
65#include <wlan_hdd_includes.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070066#include <vos_api.h>
67#include <vos_sched.h>
68#include <vos_power.h>
69#include <linux/etherdevice.h>
70#include <linux/firmware.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070071#ifdef ANI_BUS_TYPE_PLATFORM
72#include <linux/wcnss_wlan.h>
73#endif //ANI_BUS_TYPE_PLATFORM
74#ifdef ANI_BUS_TYPE_PCI
75#include "wcnss_wlan.h"
76#endif /* ANI_BUS_TYPE_PCI */
77#include <wlan_hdd_tx_rx.h>
78#include <palTimer.h>
79#include <wniApi.h>
80#include <wlan_nlink_srv.h>
81#include <wlan_btc_svc.h>
82#include <wlan_hdd_cfg.h>
83#include <wlan_ptt_sock_svc.h>
84#include <wlan_hdd_wowl.h>
85#include <wlan_hdd_misc.h>
86#include <wlan_hdd_wext.h>
87#ifdef WLAN_BTAMP_FEATURE
88#include <bap_hdd_main.h>
89#include <bapInternal.h>
90#endif // WLAN_BTAMP_FEATURE
91
Jeff Johnson295189b2012-06-20 16:38:30 -070092#include <linux/wireless.h>
93#include <net/cfg80211.h>
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +053094#include <linux/inetdevice.h>
95#include <net/addrconf.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070096#include "wlan_hdd_cfg80211.h"
97#include "wlan_hdd_p2p.h"
Jeff Johnson295189b2012-06-20 16:38:30 -070098#include <linux/rtnetlink.h>
Jeff Johnson295189b2012-06-20 16:38:30 -070099int wlan_hdd_ftm_start(hdd_context_t *pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -0700100#include "sapApi.h"
101#include <linux/semaphore.h>
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -0700102#include <linux/ctype.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700103#include <mach/subsystem_restart.h>
104#include <wlan_hdd_hostapd.h>
105#include <wlan_hdd_softap_tx_rx.h>
Jeff Johnson295189b2012-06-20 16:38:30 -0700106#include "cfgApi.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700107#include "wlan_hdd_dev_pwr.h"
108#ifdef WLAN_BTAMP_FEATURE
109#include "bap_hdd_misc.h"
110#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700111#include "wlan_qct_pal_trace.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700112#include "qwlan_version.h"
Yathish9f22e662012-12-10 14:21:35 -0800113#include "wlan_qct_wda.h"
Chilam NG571c65a2013-01-19 12:27:36 +0530114#ifdef FEATURE_WLAN_TDLS
115#include "wlan_hdd_tdls.h"
116#endif
Yue Ma0d4891e2013-08-06 17:01:45 -0700117#include "wlan_hdd_debugfs.h"
Jeff Johnson295189b2012-06-20 16:38:30 -0700118
119#ifdef MODULE
120#define WLAN_MODULE_NAME module_name(THIS_MODULE)
121#else
122#define WLAN_MODULE_NAME "wlan"
123#endif
124
125#ifdef TIMER_MANAGER
126#define TIMER_MANAGER_STR " +TIMER_MANAGER"
127#else
128#define TIMER_MANAGER_STR ""
129#endif
130
131#ifdef MEMORY_DEBUG
132#define MEMORY_DEBUG_STR " +MEMORY_DEBUG"
133#else
134#define MEMORY_DEBUG_STR ""
135#endif
136
137/* the Android framework expects this param even though we don't use it */
138#define BUF_LEN 20
Jeff Johnson76052702013-04-16 13:55:05 -0700139static char fwpath_buffer[BUF_LEN];
140static struct kparam_string fwpath = {
141 .string = fwpath_buffer,
142 .maxlen = BUF_LEN,
143};
Arif Hussain66559122013-11-21 10:11:40 -0800144
145static char *country_code;
146static int enable_11d = -1;
147static int enable_dfs_chan_scan = -1;
148
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700149#ifndef MODULE
Madan Mohan Koyyalamudidfd6aa82012-10-18 20:18:43 -0700150static int wlan_hdd_inited;
Madan Mohan Koyyalamudi05f313c2012-09-18 19:19:15 -0700151#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700152
Jeff Johnsone7245742012-09-05 17:12:55 -0700153/*
Jeff Johnson72a40512013-12-19 10:14:15 -0800154 * spinlock for synchronizing asynchronous request/response
155 * (full description of use in wlan_hdd_main.h)
156 */
157DEFINE_SPINLOCK(hdd_context_lock);
158
159/*
Jeff Johnsone7245742012-09-05 17:12:55 -0700160 * The rate at which the driver sends RESTART event to supplicant
161 * once the function 'vos_wlanRestart()' is called
162 *
163 */
164#define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */
165#define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -0700166
167/*
168 * Size of Driver command strings from upper layer
169 */
170#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */
171#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */
172
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700173#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
174#define TID_MIN_VALUE 0
175#define TID_MAX_VALUE 15
176static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
177 tAniTrafStrmMetrics* pTsmMetrics);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -0800178static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
179 tCsrCcxBeaconReq *pCcxBcnReq);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700180#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
181
Srinivas Girigowda4081bb12014-01-06 17:12:58 -0800182#define WLAN_PRIV_DATA_MAX_LEN 4096
183
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -0700184/*
185 * Driver miracast parameters 0-Disabled
186 * 1-Source, 2-Sink
187 */
188#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0
189#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2
190
Sameer Thalappil50dc0092013-02-19 17:23:33 -0800191#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -0700192static struct wake_lock wlan_wake_lock;
Jeff Johnsone7245742012-09-05 17:12:55 -0700193#endif
Jeff Johnson295189b2012-06-20 16:38:30 -0700194/* set when SSR is needed after unload */
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -0700195static e_hdd_ssr_required isSsrRequired = HDD_SSR_NOT_REQUIRED;
Jeff Johnson295189b2012-06-20 16:38:30 -0700196
197//internal function declaration
Jeff Johnsone7245742012-09-05 17:12:55 -0700198static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx);
199static void wlan_hdd_restart_init(hdd_context_t *pHddCtx);
200static void wlan_hdd_restart_deinit(hdd_context_t *pHddCtx);
201void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback);
Sameer Thalappil45931fb2013-02-01 11:18:05 -0800202void hdd_set_wlan_suspend_mode(bool suspend);
Jeff Johnsone7245742012-09-05 17:12:55 -0700203
Jeff Johnson295189b2012-06-20 16:38:30 -0700204v_U16_t hdd_select_queue(struct net_device *dev,
205 struct sk_buff *skb);
206
207#ifdef WLAN_FEATURE_PACKET_FILTERING
208static void hdd_set_multicast_list(struct net_device *dev);
209#endif
210
211void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter);
212
213extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr);
Amar Singhal0a402232013-10-11 20:57:16 -0700214
Srinivas Girigowdade697412013-02-14 16:31:48 -0800215#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
216void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand);
217static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels);
Srinivas Girigowda100eb322013-03-15 16:48:20 -0700218static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid,
219 tANI_U8 *pChannel, tANI_U8 *pDwellTime,
220 tANI_U8 **pBuf, tANI_U8 *pBufLen);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -0700221static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
222 tANI_U8 *pTargetApBssid,
223 tANI_U8 *pChannel);
Srinivas Girigowdade697412013-02-14 16:31:48 -0800224#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -0700225#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
226VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe, tANI_U8 *pCckmIeLen);
227#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
228
Mihir Shetee1093ba2014-01-21 20:13:32 +0530229static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx);
230
Jeff Johnson295189b2012-06-20 16:38:30 -0700231static int hdd_netdev_notifier_call(struct notifier_block * nb,
232 unsigned long state,
233 void *ndev)
234{
235 struct net_device *dev = ndev;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700236 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson27cee452013-03-27 11:10:24 -0700237 hdd_context_t *pHddCtx;
Jeff Johnson295189b2012-06-20 16:38:30 -0700238#ifdef WLAN_BTAMP_FEATURE
239 VOS_STATUS status;
Jeff Johnson295189b2012-06-20 16:38:30 -0700240#endif
241
242 //Make sure that this callback corresponds to our device.
Jeff Johnson27cee452013-03-27 11:10:24 -0700243 if ((strncmp(dev->name, "wlan", 4)) &&
Amar Singhal4c723bd2013-03-25 18:14:15 -0700244 (strncmp(dev->name, "p2p", 3)))
245 return NOTIFY_DONE;
246
Jeff Johnson295189b2012-06-20 16:38:30 -0700247 if (!dev->ieee80211_ptr)
Jeff Johnson27cee452013-03-27 11:10:24 -0700248 return NOTIFY_DONE;
Jeff Johnson295189b2012-06-20 16:38:30 -0700249
Jeff Johnson27cee452013-03-27 11:10:24 -0700250 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -0700251 {
Jeff Johnsona8a1a482012-12-12 16:49:33 -0800252 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Adapter Null Pointer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -0700253 VOS_ASSERT(0);
254 return NOTIFY_DONE;
255 }
256
Jeff Johnson27cee452013-03-27 11:10:24 -0700257 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
258 if (NULL == pHddCtx)
259 {
260 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD Context Null Pointer", __func__);
261 VOS_ASSERT(0);
262 return NOTIFY_DONE;
263 }
Sameer Thalappil14067972014-01-23 14:54:54 -0800264 if (pHddCtx->isLogpInProgress)
265 return NOTIFY_DONE;
266
Jeff Johnson27cee452013-03-27 11:10:24 -0700267
268 hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu",
269 __func__, dev->name, state);
Jeff Johnson295189b2012-06-20 16:38:30 -0700270
271 switch (state) {
272 case NETDEV_REGISTER:
273 break;
274
275 case NETDEV_UNREGISTER:
276 break;
277
278 case NETDEV_UP:
279 break;
280
281 case NETDEV_DOWN:
282 break;
283
284 case NETDEV_CHANGE:
Jeff Johnsone7245742012-09-05 17:12:55 -0700285 if(TRUE == pAdapter->isLinkUpSvcNeeded)
286 complete(&pAdapter->linkup_event_var);
Jeff Johnson295189b2012-06-20 16:38:30 -0700287 break;
288
289 case NETDEV_GOING_DOWN:
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -0700290 if( pHddCtx->scan_info.mScanPending != FALSE )
Jeff Johnson295189b2012-06-20 16:38:30 -0700291 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530292 long result;
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -0800293 INIT_COMPLETION(pHddCtx->scan_info.abortscan_event_var);
Srinivas, Dasari138af4f2014-02-07 11:13:45 +0530294 hdd_abort_mac_scan(pAdapter->pHddCtx, pAdapter->sessionId,
295 eCSR_SCAN_ABORT_DEFAULT);
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));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530299 if (result <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -0700300 {
301 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530302 "%s: Timeout occurred while waiting for abortscan %ld",
303 __func__, result);
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)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530548 {
549 long ret;
550
551 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700552 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530553 if (0 >= ret)
554 hddLog(LOGE, FL("failure waiting for disconnect_comp_var %ld"),
555 ret);
556 }
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700557
558 }
559}
560#else
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530561void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code)
562{
563 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
564 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
565 hdd_config_t *cfg_param;
566 eCsrPhyMode phyMode;
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530567 long ret;
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530568
569 if (NULL == pHddCtx)
570 {
571 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
572 "HDD Context is null !!");
573 return ;
574 }
575
576 cfg_param = pHddCtx->cfg_ini;
577
578 if (NULL == cfg_param)
579 {
580 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
581 "cfg_params not available !!");
582 return ;
583 }
584
585 phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter));
586
587 if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code))
588 {
589 if ((eCSR_DOT11_MODE_AUTO == phyMode) ||
590 (eCSR_DOT11_MODE_11ac == phyMode) ||
591 (eCSR_DOT11_MODE_11ac_ONLY == phyMode))
592 {
593 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
594 "Setting phymode to 11n!!");
595 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n);
596 }
597 }
598 else
599 {
600 /*New country Supports 11ac as well resetting value back from .ini*/
601 sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter),
602 hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode));
603 return ;
604 }
605
606 if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) &&
607 ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) ||
608 (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode)))
609 {
610 VOS_STATUS vosStatus;
611
612 // need to issue a disconnect to CSR.
613 INIT_COMPLETION(pAdapter->disconnect_comp_var);
614 vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter),
615 pAdapter->sessionId,
616 eCSR_DISCONNECT_REASON_UNSPECIFIED );
617
618 if (VOS_STATUS_SUCCESS == vosStatus)
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530619 {
620 ret = wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var,
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530621 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +0530622 if (ret <= 0)
623 {
624 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
625 "wait on disconnect_comp_var is failed %ld", ret);
626 }
627 }
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530628
629 }
630}
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -0700631#endif //CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +0530632
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -0700633void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code)
634{
635 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
636 hdd_config_t *cfg_param;
637
638 if (NULL == pHddCtx)
639 {
640 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
641 "HDD Context is null !!");
642 return ;
643 }
644
645 cfg_param = pHddCtx->cfg_ini;
646
647 if (NULL == cfg_param)
648 {
649 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
650 "cfg_params not available !!");
651 return ;
652 }
653
654 if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code))
655 {
656 /*New country doesn't support DFS */
657 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0);
658 }
659 else
660 {
661 /*New country Supports DFS as well resetting value back from .ini*/
662 sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan);
663 }
664
665}
666
Rajeev79dbe4c2013-10-05 11:03:42 +0530667#ifdef FEATURE_WLAN_BATCH_SCAN
668
669/**---------------------------------------------------------------------------
670
671 \brief hdd_extract_assigned_int_from_str() - Extracts assigned integer from
672 input string
673
674 This function extracts assigned integer from string in below format:
675 "STRING=10" : extracts integer 10 from this string
676
677 \param - pInPtr Pointer to input string
678 \param - base Base for string to int conversion(10 for decimal 16 for hex)
679 \param - pOutPtr Pointer to variable in which extracted integer needs to be
680 assigned
681 \param - pLastArg to tell whether it is last arguement in input string or
682 not
683
684 \return - NULL for failure cases
685 pointer to next arguement in input string for success cases
686 --------------------------------------------------------------------------*/
687static tANI_U8 *
688hdd_extract_assigned_int_from_str
689(
690 tANI_U8 *pInPtr,
691 tANI_U8 base,
692 tANI_U32 *pOutPtr,
693 tANI_U8 *pLastArg
694)
695{
696 int tempInt;
697 int v = 0;
698 char buf[32];
699 int val = 0;
700 *pLastArg = FALSE;
701
702 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
703 if (NULL == pInPtr)
704 {
705 return NULL;
706 }
707
708 pInPtr++;
709
710 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
711
712 val = sscanf(pInPtr, "%32s ", buf);
713 if (val < 0 && val > strlen(pInPtr))
714 {
715 return NULL;
716 }
717 pInPtr += val;
718 v = kstrtos32(buf, base, &tempInt);
719 if (v < 0)
720 {
721 return NULL;
722 }
Rajeev Kumar4d93d842014-01-02 18:31:21 -0800723 if (tempInt < 0)
724 {
725 tempInt = 0;
726 }
Rajeev79dbe4c2013-10-05 11:03:42 +0530727 *pOutPtr = tempInt;
728
729 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
730 if (NULL == pInPtr)
731 {
732 *pLastArg = TRUE;
733 return NULL;
734 }
735 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
736
737 return pInPtr;
738}
739
740/**---------------------------------------------------------------------------
741
742 \brief hdd_extract_assigned_char_from_str() - Extracts assigned char from
743 input string
744
745 This function extracts assigned character from string in below format:
746 "STRING=A" : extracts char 'A' from this string
747
748 \param - pInPtr Pointer to input string
749 \param - pOutPtr Pointer to variable in which extracted char needs to be
750 assigned
751 \param - pLastArg to tell whether it is last arguement in input string or
752 not
753
754 \return - NULL for failure cases
755 pointer to next arguement in input string for success cases
756 --------------------------------------------------------------------------*/
757static tANI_U8 *
758hdd_extract_assigned_char_from_str
759(
760 tANI_U8 *pInPtr,
761 tANI_U8 *pOutPtr,
762 tANI_U8 *pLastArg
763)
764{
765 *pLastArg = FALSE;
766
767 pInPtr = strnchr(pInPtr, strlen(pInPtr), EQUALS_TO_ASCII_VALUE);
768 if (NULL == pInPtr)
769 {
770 return NULL;
771 }
772
773 pInPtr++;
774
775 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
776
777 *pOutPtr = *pInPtr;
778
779 pInPtr = strnchr(pInPtr, strlen(pInPtr), SPACE_ASCII_VALUE);
780 if (NULL == pInPtr)
781 {
782 *pLastArg = TRUE;
783 return NULL;
784 }
785 while ((SPACE_ASCII_VALUE == *pInPtr) && ('\0' != *pInPtr)) pInPtr++;
786
787 return pInPtr;
788}
789
790
791/**---------------------------------------------------------------------------
792
793 \brief hdd_parse_set_batchscan_command () - HDD parse set batch scan command
794
795 This function parses set batch scan command in below format:
796 WLS_BATCHING_SET <space> followed by below arguements
797 "SCANFREQ=XX" : Optional defaults to 30 sec
798 "MSCAN=XX" : Required number of scans to attempt to batch
799 "BESTN=XX" : Best Network (RSSI) defaults to 16
800 "CHANNEL=<X,Y>" : optional defaults to all channels, can list 'A'or` B.
801 A. implies only 5 GHz , B. implies only 2.4GHz
802 "RTT=X" : optional defaults to 0
803 returns the MIN of MSCAN or the max # of scans firmware can cache or -1 on
804 error
805
806 For example input commands:
807 1) WLS_BATCHING_SET SCANFREQ=60 MSCAN=10 BESTN=20 CHANNEL=A RTT=0 -> This is
808 translated into set batch scan with following parameters:
809 a) Frequence 60 seconds
810 b) Batch 10 scans together
811 c) Best RSSI to be 20
812 d) 5GHz band only
813 e) RTT is equal to 0
814
815 \param - pValue Pointer to input channel list
816 \param - pHddSetBatchScanReq Pointer to HDD batch scan request structure
817
818 \return - 0 for success non-zero for failure
819
820 --------------------------------------------------------------------------*/
821static int
822hdd_parse_set_batchscan_command
823(
824 tANI_U8 *pValue,
825 tSirSetBatchScanReq *pHddSetBatchScanReq
826)
827{
828 tANI_U8 *inPtr = pValue;
829 tANI_U8 val = 0;
830 tANI_U8 lastArg = 0;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800831 tANI_U32 nScanFreq;
832 tANI_U32 nMscan;
833 tANI_U32 nBestN;
834 tANI_U8 ucRfBand;
835 tANI_U32 nRtt;
Rajeev Kumarc933d982013-11-18 20:04:20 -0800836 tANI_U32 temp;
Rajeev79dbe4c2013-10-05 11:03:42 +0530837
838 /*initialize default values*/
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800839 nScanFreq = HDD_SET_BATCH_SCAN_DEFAULT_FREQ;
840 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
841 nRtt = 0;
842 nBestN = HDD_SET_BATCH_SCAN_BEST_NETWORK;
Rajeev79dbe4c2013-10-05 11:03:42 +0530843
844 /*go to space after WLS_BATCHING_SET command*/
845 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
846 /*no argument after the command*/
847 if (NULL == inPtr)
848 {
849 return -EINVAL;
850 }
851
852 /*no space after the command*/
853 else if (SPACE_ASCII_VALUE != *inPtr)
854 {
855 return -EINVAL;
856 }
857
858 /*removing empty spaces*/
859 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
860
861 /*no argument followed by spaces*/
862 if ('\0' == *inPtr)
863 {
864 return -EINVAL;
865 }
866
867 /*check and parse SCANFREQ*/
868 if ((strncmp(inPtr, "SCANFREQ", 8) == 0))
869 {
870 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800871 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800872
Rajeev Kumarc933d982013-11-18 20:04:20 -0800873 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800874 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800875 nScanFreq = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800876 }
877
Rajeev79dbe4c2013-10-05 11:03:42 +0530878 if ( (NULL == inPtr) || (TRUE == lastArg))
879 {
880 return -EINVAL;
881 }
882 }
883
884 /*check and parse MSCAN*/
885 if ((strncmp(inPtr, "MSCAN", 5) == 0))
886 {
887 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800888 &nMscan, &lastArg);
889
890 if (0 == nMscan)
891 {
892 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
893 "invalid MSCAN=%d", nMscan);
894 return -EINVAL;
895 }
896
Rajeev79dbe4c2013-10-05 11:03:42 +0530897 if (TRUE == lastArg)
898 {
899 goto done;
900 }
901 else if (NULL == inPtr)
902 {
903 return -EINVAL;
904 }
905 }
906 else
907 {
908 return -EINVAL;
909 }
910
911 /*check and parse BESTN*/
912 if ((strncmp(inPtr, "BESTN", 5) == 0))
913 {
914 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumarc933d982013-11-18 20:04:20 -0800915 &temp, &lastArg);
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800916
Rajeev Kumarc933d982013-11-18 20:04:20 -0800917 if (0 != temp)
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800918 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800919 nBestN = temp;
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800920 }
921
Rajeev79dbe4c2013-10-05 11:03:42 +0530922 if (TRUE == lastArg)
923 {
924 goto done;
925 }
926 else if (NULL == inPtr)
927 {
928 return -EINVAL;
929 }
930 }
931
932 /*check and parse CHANNEL*/
933 if ((strncmp(inPtr, "CHANNEL", 7) == 0))
934 {
935 inPtr = hdd_extract_assigned_char_from_str(inPtr, &val, &lastArg);
Rajeev Kumarc933d982013-11-18 20:04:20 -0800936
Rajeev79dbe4c2013-10-05 11:03:42 +0530937 if (('A' == val) || ('a' == val))
938 {
c_hpothuebf89732014-02-25 13:00:24 +0530939 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530940 }
941 else if (('B' == val) || ('b' == val))
942 {
c_hpothuebf89732014-02-25 13:00:24 +0530943 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530944 }
945 else
946 {
Rajeev Kumarc933d982013-11-18 20:04:20 -0800947 ucRfBand = HDD_SET_BATCH_SCAN_DEFAULT_BAND;
948 }
949
950 if (TRUE == lastArg)
951 {
952 goto done;
953 }
954 else if (NULL == inPtr)
955 {
Rajeev79dbe4c2013-10-05 11:03:42 +0530956 return -EINVAL;
957 }
958 }
959
960 /*check and parse RTT*/
961 if ((strncmp(inPtr, "RTT", 3) == 0))
962 {
963 inPtr = hdd_extract_assigned_int_from_str(inPtr, 10,
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800964 &nRtt, &lastArg);
Rajeev79dbe4c2013-10-05 11:03:42 +0530965 if (TRUE == lastArg)
966 {
967 goto done;
968 }
969 if (NULL == inPtr)
970 {
971 return -EINVAL;
972 }
973 }
974
975
976done:
977
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800978 pHddSetBatchScanReq->scanFrequency = nScanFreq;
979 pHddSetBatchScanReq->numberOfScansToBatch = nMscan;
980 pHddSetBatchScanReq->bestNetwork = nBestN;
981 pHddSetBatchScanReq->rfBand = ucRfBand;
982 pHddSetBatchScanReq->rtt = nRtt;
983
Rajeev79dbe4c2013-10-05 11:03:42 +0530984 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
985 "Received WLS_BATCHING_SET with SCANFREQ=%d "
986 "MSCAN=%d BESTN=%d CHANNEL=%d RTT=%d",
987 pHddSetBatchScanReq->scanFrequency,
988 pHddSetBatchScanReq->numberOfScansToBatch,
989 pHddSetBatchScanReq->bestNetwork,
990 pHddSetBatchScanReq->rfBand,
991 pHddSetBatchScanReq->rtt);
992
993 return 0;
994}/*End of hdd_parse_set_batchscan_command*/
995
996/**---------------------------------------------------------------------------
997
998 \brief hdd_set_batch_scan_req_callback () - This function is called after
999 receiving set batch scan response from FW and it saves set batch scan
1000 response data FW to HDD context and sets the completion event on
1001 which hdd_ioctl is waiting
1002
1003 \param - callbackContext Pointer to HDD adapter
1004 \param - pRsp Pointer to set batch scan response data received from FW
1005
1006 \return - nothing
1007
1008 --------------------------------------------------------------------------*/
1009static void hdd_set_batch_scan_req_callback
1010(
1011 void *callbackContext,
1012 tSirSetBatchScanRsp *pRsp
1013)
1014{
1015 hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext;
1016 tSirSetBatchScanRsp *pHddSetBatchScanRsp;
1017
1018 /*sanity check*/
1019 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
1020 {
1021 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1022 "%s: Invalid pAdapter magic", __func__);
1023 VOS_ASSERT(0);
1024 return;
1025 }
1026 pHddSetBatchScanRsp = &pAdapter->hddSetBatchScanRsp;
1027
1028 /*save set batch scan response*/
1029 pHddSetBatchScanRsp->nScansToBatch = pRsp->nScansToBatch;
1030
1031 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
1032 "Received set batch scan rsp from FW with nScansToBatch=%d",
1033 pHddSetBatchScanRsp->nScansToBatch);
1034
1035 pAdapter->hdd_wait_for_set_batch_scan_rsp = FALSE;
1036 complete(&pAdapter->hdd_set_batch_scan_req_var);
1037
1038 return;
1039}/*End of hdd_set_batch_scan_req_callback*/
1040
1041
1042/**---------------------------------------------------------------------------
1043
1044 \brief hdd_populate_batch_scan_rsp_queue () - This function stores AP meta
1045 info in hdd batch scan response queue
1046
1047 \param - pAdapter Pointer to hdd adapter
1048 \param - pAPMetaInfo Pointer to access point meta info
1049 \param - scanId scan ID of batch scan response
1050 \param - isLastAp tells whether AP is last AP in batch scan response or not
1051
1052 \return - nothing
1053
1054 --------------------------------------------------------------------------*/
1055static void hdd_populate_batch_scan_rsp_queue( hdd_adapter_t* pAdapter,
1056 tpSirBatchScanNetworkInfo pApMetaInfo, tANI_U32 scanId, v_BOOL_t isLastAp)
1057{
1058 tHddBatchScanRsp *pHead;
1059 tHddBatchScanRsp *pNode;
1060 tHddBatchScanRsp *pPrev;
1061 tHddBatchScanRsp *pTemp;
1062 tANI_U8 ssidLen;
1063
1064 /*head of hdd batch scan response queue*/
1065 pHead = pAdapter->pBatchScanRsp;
1066
1067 pNode = (tHddBatchScanRsp *)vos_mem_malloc(sizeof(tHddBatchScanRsp));
1068 if (NULL == pNode)
1069 {
1070 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1071 "%s: Could not allocate memory", __func__);
1072 VOS_ASSERT(0);
1073 return;
1074 }
1075
1076 vos_mem_copy(pNode->ApInfo.bssid, pApMetaInfo->bssid,
1077 sizeof(pNode->ApInfo.bssid));
1078 ssidLen = strlen(pApMetaInfo->ssid);
1079 if (SIR_MAX_SSID_SIZE < ssidLen)
1080 {
1081 /*invalid scan result*/
1082 vos_mem_free(pNode);
1083 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1084 "%s: Invalid AP meta info ssidlen %d", __func__, ssidLen);
1085 return;
1086 }
1087 vos_mem_copy(pNode->ApInfo.ssid, pApMetaInfo->ssid, ssidLen);
1088 /*null terminate ssid*/
1089 pNode->ApInfo.ssid[ssidLen] = '\0';
1090 pNode->ApInfo.ch = pApMetaInfo->ch;
1091 pNode->ApInfo.rssi = pApMetaInfo->rssi;
1092 pNode->ApInfo.age = pApMetaInfo->timestamp;
1093 pNode->ApInfo.batchId = scanId;
1094 pNode->ApInfo.isLastAp = isLastAp;
1095
1096 pNode->pNext = NULL;
1097 if (NULL == pHead)
1098 {
1099 pAdapter->pBatchScanRsp = pNode;
1100 }
1101 else
1102 {
1103 pTemp = pHead;
1104 while (NULL != pTemp)
1105 {
1106 pPrev = pTemp;
1107 pTemp = pTemp->pNext;
1108 }
1109 pPrev->pNext = pNode;
1110 }
1111
1112 return;
1113}/*End of hdd_populate_batch_scan_rsp_queue*/
1114
1115/**---------------------------------------------------------------------------
1116
1117 \brief hdd_batch_scan_result_ind_callback () - This function is called after
1118 receiving batch scan response indication from FW. It saves get batch scan
1119 response data in HDD batch scan response queue. This callback sets the
1120 completion event on which hdd_ioctl is waiting only after getting complete
1121 batch scan response data from FW
1122
1123 \param - callbackContext Pointer to HDD adapter
1124 \param - pRsp Pointer to get batch scan response data received from FW
1125
1126 \return - nothing
1127
1128 --------------------------------------------------------------------------*/
1129static void hdd_batch_scan_result_ind_callback
1130(
1131 void *callbackContext,
1132 void *pRsp
1133)
1134{
1135 v_BOOL_t isLastAp;
1136 tANI_U32 numApMetaInfo;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001137 tANI_U32 numNetworkInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301138 tANI_U32 numberScanList;
1139 tANI_U32 nextScanListOffset;
1140 tANI_U32 nextApMetaInfoOffset;
1141 hdd_adapter_t* pAdapter;
1142 tpSirBatchScanList pScanList;
1143 tpSirBatchScanNetworkInfo pApMetaInfo;
1144 tpSirBatchScanResultIndParam pBatchScanRsp;/*batch scan rsp data from FW*/
1145 tSirSetBatchScanReq *pReq;
1146
1147 pAdapter = (hdd_adapter_t *)callbackContext;
1148 /*sanity check*/
Rajeev Kumar5286bb92013-12-05 11:52:10 -08001149 if ((NULL == pAdapter) || (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic))
Rajeev79dbe4c2013-10-05 11:03:42 +05301150 {
1151 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1152 "%s: Invalid pAdapter magic", __func__);
1153 VOS_ASSERT(0);
1154 return;
1155 }
1156
1157 /*initialize locals*/
1158 pReq = &pAdapter->hddSetBatchScanReq;
1159 pBatchScanRsp = (tpSirBatchScanResultIndParam)pRsp;
1160 isLastAp = FALSE;
1161 numApMetaInfo = 0;
Rajeev Kumarce651e42013-10-21 18:57:15 -07001162 numNetworkInScanList = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05301163 numberScanList = 0;
1164 nextScanListOffset = 0;
1165 nextApMetaInfoOffset = 0;
1166 pScanList = NULL;
1167 pApMetaInfo = NULL;
1168
1169 if ((NULL == pBatchScanRsp) || (NULL == pReq))
1170 {
1171 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1172 "%s: pBatchScanRsp is %p pReq %p", __func__, pBatchScanRsp, pReq);
1173 isLastAp = TRUE;
1174 goto done;
1175 }
1176
1177 pAdapter->numScanList = numberScanList = pBatchScanRsp->numScanLists;
1178 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1179 "Batch scan rsp: numberScalList %d", numberScanList);
1180
1181 if ((!numberScanList) || (numberScanList > pReq->numberOfScansToBatch))
1182 {
1183 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1184 "%s: numberScanList %d", __func__, numberScanList);
1185 isLastAp = TRUE;
1186 goto done;
1187 }
1188
1189 while (numberScanList)
1190 {
Rajeev Kumarce651e42013-10-21 18:57:15 -07001191 pScanList = (tpSirBatchScanList)((tANI_U8 *)pBatchScanRsp->scanResults +
Rajeev79dbe4c2013-10-05 11:03:42 +05301192 nextScanListOffset);
1193 if (NULL == pScanList)
1194 {
1195 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1196 "%s: pScanList is %p", __func__, pScanList);
1197 isLastAp = TRUE;
1198 goto done;
1199 }
Rajeev Kumarce651e42013-10-21 18:57:15 -07001200 numNetworkInScanList = numApMetaInfo = pScanList->numNetworksInScanList;
Rajeev79dbe4c2013-10-05 11:03:42 +05301201 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumarce651e42013-10-21 18:57:15 -07001202 "Batch scan rsp: numApMetaInfo %d scanId %d",
1203 numApMetaInfo, pScanList->scanId);
Rajeev79dbe4c2013-10-05 11:03:42 +05301204
1205 if ((!numApMetaInfo) || (numApMetaInfo > pReq->bestNetwork))
1206 {
1207 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1208 "%s: numApMetaInfo %d", __func__, numApMetaInfo);
1209 isLastAp = TRUE;
1210 goto done;
1211 }
1212
Rajeev Kumarce651e42013-10-21 18:57:15 -07001213 /*Initialize next AP meta info offset for next scan list*/
1214 nextApMetaInfoOffset = 0;
1215
Rajeev79dbe4c2013-10-05 11:03:42 +05301216 while (numApMetaInfo)
1217 {
1218 pApMetaInfo = (tpSirBatchScanNetworkInfo)(pScanList->scanList +
1219 nextApMetaInfoOffset);
1220 if (NULL == pApMetaInfo)
1221 {
1222 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1223 "%s: pApMetaInfo is %p", __func__, pApMetaInfo);
1224 isLastAp = TRUE;
1225 goto done;
1226 }
1227 /*calculate AP age*/
1228 pApMetaInfo->timestamp =
1229 pBatchScanRsp->timestamp - pApMetaInfo->timestamp;
1230
1231 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
Arif Hussaina7c8e412013-11-20 11:06:42 -08001232 "%s: bssId "MAC_ADDRESS_STR
1233 " ch %d rssi %d timestamp %d", __func__,
1234 MAC_ADDR_ARRAY(pApMetaInfo->bssid),
1235 pApMetaInfo->ch, pApMetaInfo->rssi,
1236 pApMetaInfo->timestamp);
Rajeev79dbe4c2013-10-05 11:03:42 +05301237
1238 /*mark last AP in batch scan response*/
1239 if ((TRUE == pBatchScanRsp->isLastResult) &&
1240 (1 == numberScanList) && (1 == numApMetaInfo))
1241 {
1242 isLastAp = TRUE;
1243 }
1244
1245 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1246 /*store batch scan repsonse in hdd queue*/
1247 hdd_populate_batch_scan_rsp_queue(pAdapter, pApMetaInfo,
1248 pScanList->scanId, isLastAp);
1249 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1250
1251 nextApMetaInfoOffset += sizeof(tSirBatchScanNetworkInfo);
1252 numApMetaInfo--;
1253 }
1254
Rajeev Kumarce651e42013-10-21 18:57:15 -07001255 nextScanListOffset += ((sizeof(tSirBatchScanList) - sizeof(tANI_U8))
1256 + (sizeof(tSirBatchScanNetworkInfo)
1257 * numNetworkInScanList));
Rajeev79dbe4c2013-10-05 11:03:42 +05301258 numberScanList--;
1259 }
1260
1261done:
1262
1263 /*notify hdd_ioctl only if complete batch scan rsp is received and it was
1264 requested from hdd_ioctl*/
1265 if ((TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp) &&
1266 (TRUE == isLastAp))
1267 {
1268 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1269 complete(&pAdapter->hdd_get_batch_scan_req_var);
1270 }
1271
1272 return;
1273}/*End of hdd_batch_scan_result_ind_callback*/
1274
1275/**---------------------------------------------------------------------------
1276
1277 \brief hdd_format_batch_scan_rsp () - This function formats batch scan
1278 response as per batch scan FR request format by putting proper markers
1279
1280 \param - pDest pointer to destination buffer
1281 \param - cur_len current length
1282 \param - tot_len total remaining size which can be written to user space
1283 \param - pApMetaInfo Pointer to get batch scan response AP meta info
1284 \param - pAdapter Pointer to HDD adapter
1285
1286 \return - ret no of characters written
1287
1288 --------------------------------------------------------------------------*/
1289static tANI_U32
1290hdd_format_batch_scan_rsp
1291(
1292 tANI_U8 *pDest,
1293 tANI_U32 cur_len,
1294 tANI_U32 tot_len,
1295 tHddBatchScanRsp *pApMetaInfo,
1296 hdd_adapter_t* pAdapter
1297)
1298{
1299 tANI_U32 ret = 0;
1300 tANI_U32 rem_len = 0;
1301 tANI_U8 temp_len = 0;
1302 tANI_U8 temp_total_len = 0;
1303 tANI_U8 temp[HDD_BATCH_SCAN_AP_META_INFO_SIZE];
1304 tANI_U8 *pTemp = temp;
1305
1306 /*Batch scan reponse needs to be returned to user space in
1307 following format:
1308 "scancount=X\n" where X is the number of scans in current batch
1309 batch
1310 "trunc\n" optional present if current scan truncated
1311 "bssid=XX:XX:XX:XX:XX:XX\n"
1312 "ssid=XXXX\n"
1313 "freq=X\n" frequency in Mhz
1314 "level=XX\n"
1315 "age=X\n" ms
1316 "dist=X\n" cm (-1 if not available)
1317 "errror=X\n" (-1if not available)
1318 "====\n" (end of ap marker)
1319 "####\n" (end of scan marker)
1320 "----\n" (end of results)*/
1321 /*send scan result in above format to user space based on
1322 available length*/
1323 /*The GET response may have more data than the driver can return in its
1324 buffer. In that case the buffer should be filled to the nearest complete
1325 scan, ending with "%%%%".Subsequent callsshould return the remaining data
1326 starting with the next scan (optional .trunc\n., .apcount=X\n., etc).
1327 The final buffer should end with "----\n"*/
1328
1329 /*sanity*/
1330 if (cur_len > tot_len)
1331 {
1332 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1333 "%s: invaid cur_len %d tot_len %d", __func__, cur_len, tot_len);
1334 return 0;
1335 }
1336 else
1337 {
1338 rem_len = (tot_len - cur_len);
1339 }
1340
1341 /*end scan marker*/
1342 if (pApMetaInfo->ApInfo.batchId != pAdapter->prev_batch_id)
1343 {
1344 temp_len = snprintf(pTemp, sizeof(temp), "####\n");
1345 pTemp += temp_len;
1346 temp_total_len += temp_len;
1347 }
1348
1349 /*bssid*/
1350 temp_len = snprintf(pTemp, sizeof(temp),
1351 "bssid=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x\n",
1352 pApMetaInfo->ApInfo.bssid[0], pApMetaInfo->ApInfo.bssid[1],
1353 pApMetaInfo->ApInfo.bssid[2], pApMetaInfo->ApInfo.bssid[3],
1354 pApMetaInfo->ApInfo.bssid[4], pApMetaInfo->ApInfo.bssid[5]);
1355 pTemp += temp_len;
1356 temp_total_len += temp_len;
1357
1358 /*ssid*/
1359 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "ssid=%s\n",
1360 pApMetaInfo->ApInfo.ssid);
1361 pTemp += temp_len;
1362 temp_total_len += temp_len;
1363
1364 /*freq*/
1365 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "freq=%d\n",
Rajeev Kumarc40f7512013-11-04 14:13:23 -08001366 sme_ChnToFreq(pApMetaInfo->ApInfo.ch));
Rajeev79dbe4c2013-10-05 11:03:42 +05301367 pTemp += temp_len;
1368 temp_total_len += temp_len;
1369
1370 /*level*/
1371 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "level=%d\n",
1372 pApMetaInfo->ApInfo.rssi);
1373 pTemp += temp_len;
1374 temp_total_len += temp_len;
1375
1376 /*age*/
Jeff Johnson02797792013-10-26 19:17:13 -07001377 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "age=%d\n",
Rajeev79dbe4c2013-10-05 11:03:42 +05301378 pApMetaInfo->ApInfo.age);
1379 pTemp += temp_len;
1380 temp_total_len += temp_len;
1381
1382 /*dist*/
1383 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "dist=-1\n");
1384 pTemp += temp_len;
1385 temp_total_len += temp_len;
1386
1387 /*error*/
1388 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "error=-1\n");
1389 pTemp += temp_len;
1390 temp_total_len += temp_len;
1391
1392 /*end AP marker*/
1393 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "====\n");
1394 pTemp += temp_len;
1395 temp_total_len += temp_len;
1396
1397 /*last AP in batch scan response*/
1398 if(TRUE == pApMetaInfo->ApInfo.isLastAp)
1399 {
1400 /*end scan marker*/
1401 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "####\n");
1402 pTemp += temp_len;
1403 temp_total_len += temp_len;
1404
1405 /*end batch scan result marker*/
1406 temp_len = snprintf(pTemp, (sizeof(temp) - temp_total_len), "----\n");
1407 pTemp += temp_len;
1408 temp_total_len += temp_len;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001409
Rajeev79dbe4c2013-10-05 11:03:42 +05301410 }
1411
1412 if (temp_total_len < rem_len)
1413 {
1414 ret = temp_total_len + 1;
1415 strlcpy(pDest, temp, ret);
1416 pAdapter->isTruncated = FALSE;
1417 }
1418 else
1419 {
1420 pAdapter->isTruncated = TRUE;
1421 if (rem_len >= strlen("%%%%"))
1422 {
Rajeev Kumarc933d982013-11-18 20:04:20 -08001423 ret = snprintf(pDest, sizeof(temp), "%%%%");
Rajeev79dbe4c2013-10-05 11:03:42 +05301424 }
Rajeev Kumarc933d982013-11-18 20:04:20 -08001425 else
Rajeev79dbe4c2013-10-05 11:03:42 +05301426 {
1427 ret = 0;
1428 }
1429 }
1430
1431 return ret;
1432
1433}/*End of hdd_format_batch_scan_rsp*/
1434
1435/**---------------------------------------------------------------------------
1436
1437 \brief hdd_populate_user_batch_scan_rsp() - This function populates user data
1438 buffer starting with head of hdd batch scan response queue
1439
1440 \param - pAdapter Pointer to HDD adapter
1441 \param - pDest Pointer to user data buffer
1442 \param - cur_len current offset in user buffer
1443 \param - rem_len remaining no of bytes in user buffer
1444
1445 \return - number of bytes written in user buffer
1446
1447 --------------------------------------------------------------------------*/
1448
1449tANI_U32 hdd_populate_user_batch_scan_rsp
1450(
1451 hdd_adapter_t* pAdapter,
1452 tANI_U8 *pDest,
1453 tANI_U32 cur_len,
1454 tANI_U32 rem_len
1455)
1456{
1457 tHddBatchScanRsp *pHead;
1458 tHddBatchScanRsp *pPrev;
1459 tANI_U32 len;
1460
Rajeev79dbe4c2013-10-05 11:03:42 +05301461 pAdapter->isTruncated = FALSE;
1462
1463 /*head of hdd batch scan response queue*/
1464 pHead = pAdapter->pBatchScanRsp;
1465 while (pHead)
1466 {
1467 len = hdd_format_batch_scan_rsp(pDest, cur_len, rem_len, pHead,
1468 pAdapter);
1469 pDest += len;
Rajeev Kumar292d2bb2013-10-23 15:01:44 -07001470 pDest--;
Rajeev79dbe4c2013-10-05 11:03:42 +05301471 cur_len += len;
1472 if(TRUE == pAdapter->isTruncated)
1473 {
1474 /*result is truncated return rest of scan rsp in next req*/
1475 cur_len = rem_len;
1476 break;
1477 }
1478 pPrev = pHead;
1479 pHead = pHead->pNext;
1480 pAdapter->pBatchScanRsp = pHead;
Rajeev Kumarbe17d8b2014-01-10 15:39:45 -08001481 if (TRUE == pPrev->ApInfo.isLastAp)
1482 {
1483 pAdapter->prev_batch_id = 0;
1484 }
1485 else
1486 {
1487 pAdapter->prev_batch_id = pPrev->ApInfo.batchId;
1488 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301489 vos_mem_free(pPrev);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08001490 pPrev = NULL;
Rajeev79dbe4c2013-10-05 11:03:42 +05301491 }
1492
1493 return cur_len;
1494}/*End of hdd_populate_user_batch_scan_rsp*/
1495
1496/**---------------------------------------------------------------------------
1497
1498 \brief hdd_return_batch_scan_rsp_to_user () - This function returns batch
1499 scan response data from HDD queue to user space
1500 It does following in detail:
1501 a) if HDD has enough data in its queue then it 1st copies data to user
1502 space and then send get batch scan indication message to FW. In this
1503 case it does not wait on any event and batch scan response data will
1504 be populated in HDD response queue in MC thread context after receiving
1505 indication from FW
1506 b) else send get batch scan indication message to FW and wait on an event
1507 which will be set once HDD receives complete batch scan response from
1508 FW and then this function returns batch scan response to user space
1509
1510 \param - pAdapter Pointer to HDD adapter
1511 \param - pPrivData Pointer to priv_data
1512
1513 \return - 0 for success -EFAULT for failure
1514
1515 --------------------------------------------------------------------------*/
1516
1517int hdd_return_batch_scan_rsp_to_user
1518(
1519 hdd_adapter_t* pAdapter,
1520 hdd_priv_data_t *pPrivData,
1521 tANI_U8 *command
1522)
1523{
1524 tANI_U8 *pDest;
1525 tANI_U32 count = 0;
1526 tANI_U32 len = 0;
1527 tANI_U32 cur_len = 0;
1528 tANI_U32 rem_len = 0;
1529 eHalStatus halStatus;
1530 unsigned long rc;
1531 tSirTriggerBatchScanResultInd *pReq;
1532
1533 pReq = &pAdapter->hddTriggerBatchScanResultInd;
1534 pReq->param = 0;/*batch scan client*/
1535 pDest = (tANI_U8 *)(command + pPrivData->used_len);
1536 pAdapter->hdd_wait_for_get_batch_scan_rsp = FALSE;
1537
1538 cur_len = pPrivData->used_len;
1539 if (pPrivData->total_len > pPrivData->used_len)
1540 {
1541 rem_len = pPrivData->total_len - pPrivData->used_len;
1542 }
1543 else
1544 {
1545 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1546 "%s: Invalid user data buffer total_len %d used_len %d",
1547 __func__, pPrivData->total_len, pPrivData->used_len);
1548 return -EFAULT;
1549 }
1550
1551 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1552 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1553 cur_len, rem_len);
1554 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1555
1556 /*enough scan result available in cache to return to user space or
1557 scan result needs to be fetched 1st from fw and then return*/
Rajeev Kumar99db6262013-11-11 15:23:36 -08001558 if (len == cur_len)
Rajeev79dbe4c2013-10-05 11:03:42 +05301559 {
1560 pAdapter->hdd_wait_for_get_batch_scan_rsp = TRUE;
1561 halStatus = sme_TriggerBatchScanResultInd(
1562 WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1563 pAdapter->sessionId, hdd_batch_scan_result_ind_callback,
1564 pAdapter);
1565 if ( eHAL_STATUS_SUCCESS == halStatus )
1566 {
1567 if (TRUE == pAdapter->hdd_wait_for_get_batch_scan_rsp)
1568 {
1569 INIT_COMPLETION(pAdapter->hdd_get_batch_scan_req_var);
1570 rc = wait_for_completion_timeout(
1571 &pAdapter->hdd_get_batch_scan_req_var,
1572 msecs_to_jiffies(HDD_GET_BATCH_SCAN_RSP_TIME_OUT));
1573 if (0 == rc)
1574 {
1575 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1576 "%s: Timeout waiting to fetch batch scan rsp from fw",
1577 __func__);
1578 return -EFAULT;
1579 }
1580 }
1581
1582 len = snprintf(pDest, HDD_BATCH_SCAN_AP_META_INFO_SIZE,
Jeff Johnson02797792013-10-26 19:17:13 -07001583 "scancount=%u\n", pAdapter->numScanList);
Rajeev79dbe4c2013-10-05 11:03:42 +05301584 pDest += len;
1585 cur_len += len;
1586
1587 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1588 len = hdd_populate_user_batch_scan_rsp(pAdapter, pDest,
1589 cur_len, rem_len);
1590 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1591
1592 count = 0;
1593 len = (len - pPrivData->used_len);
1594 pDest = (command + pPrivData->used_len);
1595 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001596 "NEW BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301597 while(count < len)
1598 {
1599 printk("%c", *(pDest + count));
1600 count++;
1601 }
1602 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1603 "%s: copy %d data to user buffer", __func__, len);
1604 if (copy_to_user(pPrivData->buf, pDest, len))
1605 {
1606 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1607 "%s: failed to copy data to user buffer", __func__);
1608 return -EFAULT;
1609 }
1610 }
1611 else
1612 {
1613 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1614 "sme_GetBatchScanScan returned failure halStatus %d",
1615 halStatus);
1616 return -EINVAL;
1617 }
1618 }
1619 else
1620 {
Rajeev79dbe4c2013-10-05 11:03:42 +05301621 count = 0;
1622 len = (len - pPrivData->used_len);
1623 pDest = (command + pPrivData->used_len);
1624 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Rajeev Kumar99db6262013-11-11 15:23:36 -08001625 "REMAINING TRUNCATED BATCH SCAN RESULT:");
Rajeev79dbe4c2013-10-05 11:03:42 +05301626 while(count < len)
1627 {
1628 printk("%c", *(pDest + count));
1629 count++;
1630 }
Rajeev Kumar99db6262013-11-11 15:23:36 -08001631 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1632 "%s: copy %d data to user buffer", __func__, len);
Rajeev79dbe4c2013-10-05 11:03:42 +05301633 if (copy_to_user(pPrivData->buf, pDest, len))
1634 {
1635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1636 "%s: failed to copy data to user buffer", __func__);
1637 return -EFAULT;
1638 }
Rajeev79dbe4c2013-10-05 11:03:42 +05301639 }
1640
1641 return 0;
1642} /*End of hdd_return_batch_scan_rsp_to_user*/
1643
Rajeev Kumar8b373292014-01-08 20:36:55 -08001644
1645/**---------------------------------------------------------------------------
1646
1647 \brief hdd_handle_batch_scan_ioctl () - This function handles WLS_BATCHING
1648 IOCTLs from user space. Following BATCH SCAN DEV IOCTs are handled:
1649 WLS_BATCHING VERSION
1650 WLS_BATCHING SET
1651 WLS_BATCHING GET
1652 WLS_BATCHING STOP
1653
1654 \param - pAdapter Pointer to HDD adapter
1655 \param - pPrivdata Pointer to priv_data
1656 \param - command Pointer to command
1657
1658 \return - 0 for success -EFAULT for failure
1659
1660 --------------------------------------------------------------------------*/
1661
1662int hdd_handle_batch_scan_ioctl
1663(
1664 hdd_adapter_t *pAdapter,
1665 hdd_priv_data_t *pPrivdata,
1666 tANI_U8 *command
1667)
1668{
1669 int ret = 0;
1670
1671 if (strncmp(command, "WLS_BATCHING VERSION", 20) == 0)
1672 {
1673 char extra[32];
1674 tANI_U8 len = 0;
1675 tANI_U8 version = HDD_BATCH_SCAN_VERSION;
1676
1677 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1678 {
1679 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1680 "%s: Batch scan feature is not supported by FW", __func__);
1681 ret = -EINVAL;
1682 goto exit;
1683 }
1684
1685 len = scnprintf(extra, sizeof(extra), "WLS_BATCHING_VERSION %d",
1686 version);
1687 if (copy_to_user(pPrivdata->buf, &extra, len + 1))
1688 {
1689 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1690 "%s: failed to copy data to user buffer", __func__);
1691 ret = -EFAULT;
1692 goto exit;
1693 }
1694 ret = HDD_BATCH_SCAN_VERSION;
1695 }
1696 else if (strncmp(command, "WLS_BATCHING SET", 16) == 0)
1697 {
1698 int status;
1699 tANI_U8 *value = (command + 16);
1700 eHalStatus halStatus;
1701 unsigned long rc;
1702 tSirSetBatchScanReq *pReq = &pAdapter->hddSetBatchScanReq;
1703 tSirSetBatchScanRsp *pRsp = &pAdapter->hddSetBatchScanRsp;
1704
1705 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1706 {
1707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1708 "%s: Batch scan feature is not supported by FW", __func__);
1709 ret = -EINVAL;
1710 goto exit;
1711 }
1712
1713 if ((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) &&
1714 (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) &&
1715 (WLAN_HDD_P2P_GO != pAdapter->device_mode) &&
1716 (WLAN_HDD_P2P_DEVICE != pAdapter->device_mode))
1717 {
1718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1719 "Received WLS_BATCHING SET command in invalid mode %d "
1720 "WLS_BATCHING_SET is only allowed in infra STA/P2P client mode",
1721 pAdapter->device_mode);
1722 ret = -EINVAL;
1723 goto exit;
1724 }
1725
1726 status = hdd_parse_set_batchscan_command(value, pReq);
1727 if (status)
1728 {
1729 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1730 "Invalid WLS_BATCHING SET command");
1731 ret = -EINVAL;
1732 goto exit;
1733 }
1734
1735
1736 pAdapter->hdd_wait_for_set_batch_scan_rsp = TRUE;
1737 halStatus = sme_SetBatchScanReq(WLAN_HDD_GET_HAL_CTX(pAdapter), pReq,
1738 pAdapter->sessionId, hdd_set_batch_scan_req_callback,
1739 pAdapter);
1740
1741 if ( eHAL_STATUS_SUCCESS == halStatus )
1742 {
1743 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1744 "sme_SetBatchScanReq returned success halStatus %d",
1745 halStatus);
1746 if (TRUE == pAdapter->hdd_wait_for_set_batch_scan_rsp)
1747 {
1748 INIT_COMPLETION(pAdapter->hdd_set_batch_scan_req_var);
1749 rc = wait_for_completion_timeout(
1750 &pAdapter->hdd_set_batch_scan_req_var,
1751 msecs_to_jiffies(HDD_SET_BATCH_SCAN_REQ_TIME_OUT));
1752 if (0 == rc)
1753 {
1754 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1755 "%s: Timeout waiting for set batch scan to complete",
1756 __func__);
1757 ret = -EINVAL;
1758 goto exit;
1759 }
1760 }
1761 if ( !pRsp->nScansToBatch )
1762 {
1763 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1764 "%s: Received set batch scan failure response from FW",
1765 __func__);
1766 ret = -EINVAL;
1767 goto exit;
1768 }
1769 /*As per the Batch Scan Framework API we should return the MIN of
1770 either MSCAN or the max # of scans firmware can cache*/
1771 ret = MIN(pReq->numberOfScansToBatch , pRsp->nScansToBatch);
1772
1773 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STARTED;
1774
1775 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1776 "%s: request MSCAN %d response MSCAN %d ret %d",
1777 __func__, pReq->numberOfScansToBatch, pRsp->nScansToBatch, ret);
1778 }
1779 else
1780 {
1781 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1782 "sme_SetBatchScanReq returned failure halStatus %d",
1783 halStatus);
1784 ret = -EINVAL;
1785 goto exit;
1786 }
1787 }
1788 else if (strncmp(command, "WLS_BATCHING STOP", 17) == 0)
1789 {
1790 eHalStatus halStatus;
1791 tSirStopBatchScanInd *pInd = &pAdapter->hddStopBatchScanInd;
1792 pInd->param = 0;
1793
1794 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1795 {
1796 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1797 "%s: Batch scan feature is not supported by FW", __func__);
1798 ret = -EINVAL;
1799 goto exit;
1800 }
1801
1802 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1803 {
1804 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1805 "Batch scan is not yet enabled batch scan state %d",
1806 pAdapter->batchScanState);
1807 ret = -EINVAL;
1808 goto exit;
1809 }
1810
Kiet Lamaa8e15a2014-02-11 23:30:06 -08001811 mutex_lock(&pAdapter->hdd_batch_scan_lock);
1812 hdd_deinit_batch_scan(pAdapter);
1813 mutex_unlock(&pAdapter->hdd_batch_scan_lock);
1814
Rajeev Kumar8b373292014-01-08 20:36:55 -08001815 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
1816
1817 halStatus = sme_StopBatchScanInd(WLAN_HDD_GET_HAL_CTX(pAdapter), pInd,
1818 pAdapter->sessionId);
1819 if ( eHAL_STATUS_SUCCESS == halStatus )
1820 {
1821 ret = 0;
1822 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1823 "sme_StopBatchScanInd returned success halStatus %d",
1824 halStatus);
1825 }
1826 else
1827 {
1828 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1829 "sme_StopBatchScanInd returned failure halStatus %d",
1830 halStatus);
1831 ret = -EINVAL;
1832 goto exit;
1833 }
1834 }
1835 else if (strncmp(command, "WLS_BATCHING GET", 16) == 0)
1836 {
1837 tANI_U32 remain_len;
1838
1839 if (FALSE == sme_IsFeatureSupportedByFW(BATCH_SCAN))
1840 {
1841 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1842 "%s: Batch scan feature is not supported by FW", __func__);
1843 ret = -EINVAL;
1844 goto exit;
1845 }
1846
1847 if (eHDD_BATCH_SCAN_STATE_STARTED != pAdapter->batchScanState)
1848 {
1849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1850 "Batch scan is not yet enabled could not return results"
1851 "Batch Scan state %d",
1852 pAdapter->batchScanState);
1853 ret = -EINVAL;
1854 goto exit;
1855 }
1856
1857 pPrivdata->used_len = 16;
1858 remain_len = pPrivdata->total_len - pPrivdata->used_len;
1859 if (remain_len < pPrivdata->total_len)
1860 {
1861 /*Clear previous batch scan response data if any*/
1862 vos_mem_zero((tANI_U8 *)(command + pPrivdata->used_len), remain_len);
1863 }
1864 else
1865 {
1866 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1867 "Invalid total length from user space can't fetch batch"
1868 " scan response total_len %d used_len %d remain len %d",
1869 pPrivdata->total_len, pPrivdata->used_len, remain_len);
1870 ret = -EINVAL;
1871 goto exit;
1872 }
1873 ret = hdd_return_batch_scan_rsp_to_user(pAdapter, pPrivdata, command);
1874 }
1875
1876exit:
1877
1878 return ret;
1879}
1880
1881
Rajeev79dbe4c2013-10-05 11:03:42 +05301882#endif/*End of FEATURE_WLAN_BATCH_SCAN*/
1883
Jeff Johnson295189b2012-06-20 16:38:30 -07001884int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1885{
1886 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
1887 hdd_priv_data_t priv_data;
1888 tANI_U8 *command = NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301889 long ret = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07001890
1891 if (NULL == pAdapter)
1892 {
1893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05301894 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001895 ret = -ENODEV;
1896 goto exit;
1897 }
1898
Jeff Johnsone7245742012-09-05 17:12:55 -07001899 if ((!ifr) || (!ifr->ifr_data))
Jeff Johnson295189b2012-06-20 16:38:30 -07001900 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301901 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1902 "%s: invalid data", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001903 ret = -EINVAL;
1904 goto exit;
1905 }
1906
Sameer Thalappil8ef3a0e2013-04-05 14:36:04 -07001907 if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress)
1908 {
1909 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
1910 "%s:LOGP in Progress. Ignore!!!", __func__);
1911 ret = -EBUSY;
1912 goto exit;
1913 }
1914
Jeff Johnson295189b2012-06-20 16:38:30 -07001915 if (copy_from_user(&priv_data, ifr->ifr_data, sizeof(hdd_priv_data_t)))
1916 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301917 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1918 FL("failed to get data from user buffer"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001919 ret = -EFAULT;
1920 goto exit;
1921 }
1922
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08001923 if (priv_data.total_len <= 0 ||
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301924 priv_data.total_len > WLAN_PRIV_DATA_MAX_LEN)
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001925 {
1926 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
1927 "%s:invalid priv_data.total_len(%d)!!!", __func__,
1928 priv_data.total_len);
1929 ret = -EINVAL;
1930 goto exit;
1931 }
1932
1933 /* Allocate +1 for '\0' */
1934 command = kmalloc(priv_data.total_len + 1, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07001935 if (!command)
1936 {
1937 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301938 "%s: failed to allocate memory", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001939 ret = -ENOMEM;
1940 goto exit;
1941 }
1942
1943 if (copy_from_user(command, priv_data.buf, priv_data.total_len))
1944 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301945 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
1946 FL("failed to get data from user buffer"));
Jeff Johnson295189b2012-06-20 16:38:30 -07001947 ret = -EFAULT;
1948 goto exit;
1949 }
1950
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07001951 /* Making sure the command is NUL-terminated */
1952 command[priv_data.total_len] = '\0';
1953
Jeff Johnson295189b2012-06-20 16:38:30 -07001954 if ((SIOCDEVPRIVATE + 1) == cmd)
1955 {
1956 hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
1957
1958 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07001959 "%s: Received %s cmd from Wi-Fi GUI***", __func__, command);
Jeff Johnson295189b2012-06-20 16:38:30 -07001960
1961 if (strncmp(command, "P2P_DEV_ADDR", 12) == 0 )
1962 {
1963 if (copy_to_user(priv_data.buf, pHddCtx->p2pDeviceAddress.bytes,
1964 sizeof(tSirMacAddr)))
1965 {
1966 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Arif Hussain6d2a3322013-11-17 19:50:10 -08001967 "%s: failed to copy data to user buffer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07001968 ret = -EFAULT;
1969 }
1970 }
Amar Singhal0974e402013-02-12 14:27:46 -08001971 else if(strncmp(command, "SETBAND", 7) == 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07001972 {
Amar Singhal0974e402013-02-12 14:27:46 -08001973 tANI_U8 *ptr = command ;
Srinivas Girigowdade697412013-02-14 16:31:48 -08001974
Jeff Johnson295189b2012-06-20 16:38:30 -07001975 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001976
1977 /* First 8 bytes will have "SETBAND " and
Jeff Johnson295189b2012-06-20 16:38:30 -07001978 * 9 byte will have band setting value */
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07001979 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Amar Singhal0974e402013-02-12 14:27:46 -08001980 "%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 -07001981 /* Change band request received */
Srinivas Girigowdade697412013-02-14 16:31:48 -08001982 ret = hdd_setBand_helper(dev, ptr);
c_hpothu6ff1c3c2013-10-01 19:01:57 +05301983 if(ret != 0)
1984 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
1985 "%s: failed to set band ret=%ld",__func__, ret);
Srinivas Girigowdade697412013-02-14 16:31:48 -08001986 }
Kiet Lamf040f472013-11-20 21:15:23 +05301987 else if(strncmp(command, "SETWMMPS", 8) == 0)
1988 {
1989 tANI_U8 *ptr = command;
1990 ret = hdd_wmmps_helper(pAdapter, ptr);
1991 }
Jeff Johnson32d95a32012-09-10 13:15:23 -07001992 else if ( strncasecmp(command, "COUNTRY", 7) == 0 )
1993 {
1994 char *country_code;
1995
1996 country_code = command + 8;
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001997
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07001998 INIT_COMPLETION(pAdapter->change_country_code);
Tushnim Bhattacharyya9cdf6082013-04-21 16:33:30 -07001999 hdd_checkandupdate_dfssetting(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002000#ifndef CONFIG_ENABLE_LINUX_REG
Gopichand Nakkaladacbcb52013-04-18 16:41:54 +05302001 hdd_checkandupdate_phymode(pAdapter, country_code);
Tushnim Bhattacharyya71ccecc2013-10-14 16:22:56 -07002002#endif
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002003 ret = (int)sme_ChangeCountryCode(pHddCtx->hHal,
2004 (void *)(tSmeChangeCountryCallback)
2005 wlan_hdd_change_country_code_callback,
Abhishek Singha306a442013-11-07 18:39:01 +05302006 country_code, pAdapter, pHddCtx->pvosContext, eSIR_TRUE, eSIR_TRUE);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002007 if (eHAL_STATUS_SUCCESS == ret)
2008 {
2009 ret = wait_for_completion_interruptible_timeout(
2010 &pAdapter->change_country_code,
2011 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
2012 if (0 >= ret)
2013 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302014 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: SME while setting country code timed out %ld",
2015 __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002016 }
2017 }
2018 else
Jeff Johnson32d95a32012-09-10 13:15:23 -07002019 {
2020 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05302021 "%s: SME Change Country code fail ret=%ld", __func__, ret);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002022 ret = -EINVAL;
Jeff Johnson32d95a32012-09-10 13:15:23 -07002023 }
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07002024
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002025 }
2026 /*
2027 command should be a string having format
2028 SET_SAP_CHANNEL_LIST <num of channels> <the channels seperated by spaces>
2029 */
Amar Singhal0974e402013-02-12 14:27:46 -08002030 else if(strncmp(command, "SET_SAP_CHANNEL_LIST", 20) == 0)
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002031 {
Amar Singhal0974e402013-02-12 14:27:46 -08002032 tANI_U8 *ptr = command;
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002033
2034 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07002035 " Received Command to Set Preferred Channels for SAP in %s", __func__);
Madan Mohan Koyyalamudi1bed5982012-10-22 14:38:06 -07002036
Mahesh Kumar Kalikot Veetil2aad8d82013-02-07 12:31:28 -08002037 ret = sapSetPreferredChannel(ptr);
Jeff Johnson32d95a32012-09-10 13:15:23 -07002038 }
Sameer Thalappil45931fb2013-02-01 11:18:05 -08002039 else if(strncmp(command, "SETSUSPENDMODE", 14) == 0)
2040 {
2041 int suspend = 0;
2042 tANI_U8 *ptr = (tANI_U8*)command + 15;
2043
2044 suspend = *ptr - '0';
2045 hdd_set_wlan_suspend_mode(suspend);
2046 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002047#ifdef WLAN_FEATURE_NEIGHBOR_ROAMING
2048 else if (strncmp(command, "SETROAMTRIGGER", 14) == 0)
2049 {
2050 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002051 tANI_S8 rssi = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002052 tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT;
2053 eHalStatus status = eHAL_STATUS_SUCCESS;
2054
2055 /* Move pointer to ahead of SETROAMTRIGGER<delimiter> */
2056 value = value + 15;
2057
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002058 /* Convert the value from ascii to integer */
2059 ret = kstrtos8(value, 10, &rssi);
2060 if (ret < 0)
2061 {
2062 /* If the input value is greater than max value of datatype, then also
2063 kstrtou8 fails */
2064 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2065 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdafa7157d2013-10-31 10:14:22 -07002066 __func__,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002067 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2068 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2069 ret = -EINVAL;
2070 goto exit;
2071 }
2072
Srinivas Girigowdade697412013-02-14 16:31:48 -08002073 lookUpThreshold = abs(rssi);
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002074
Srinivas Girigowdade697412013-02-14 16:31:48 -08002075 if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) ||
2076 (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX))
2077 {
2078 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2079 "Neighbor lookup threshold value %d is out of range"
2080 " (Min: %d Max: %d)", lookUpThreshold,
2081 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN,
2082 CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX);
2083 ret = -EINVAL;
2084 goto exit;
2085 }
2086
2087 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2088 "%s: Received Command to Set Roam trigger"
2089 " (Neighbor lookup threshold) = %d", __func__, lookUpThreshold);
2090
2091 pHddCtx->cfg_ini->nNeighborLookupRssiThreshold = lookUpThreshold;
2092 status = sme_setNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold);
2093 if (eHAL_STATUS_SUCCESS != status)
2094 {
2095 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2096 "%s: Failed to set roam trigger, try again", __func__);
2097 ret = -EPERM;
2098 goto exit;
2099 }
2100
2101 /* Set Reassoc threshold to (lookup rssi threshold + 5 dBm) */
2102 sme_setNeighborReassocRssiThreshold((tHalHandle)(pHddCtx->hHal), lookUpThreshold + 5);
2103 }
2104 else if (strncmp(command, "GETROAMTRIGGER", 14) == 0)
2105 {
2106 tANI_U8 lookUpThreshold = sme_getNeighborLookupRssiThreshold((tHalHandle)(pHddCtx->hHal));
2107 int rssi = (-1) * lookUpThreshold;
2108 char extra[32];
2109 tANI_U8 len = 0;
2110
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002111 len = scnprintf(extra, sizeof(extra), "%s %d", command, rssi);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002112 if (copy_to_user(priv_data.buf, &extra, len + 1))
2113 {
2114 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2115 "%s: failed to copy data to user buffer", __func__);
2116 ret = -EFAULT;
2117 goto exit;
2118 }
2119 }
2120 else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0)
2121 {
2122 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002123 tANI_U8 roamScanPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002124 tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002125
Srinivas Girigowdade697412013-02-14 16:31:48 -08002126 /* input refresh period is in terms of seconds */
2127 /* Move pointer to ahead of SETROAMSCANPERIOD<delimiter> */
2128 value = value + 18;
2129 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002130 ret = kstrtou8(value, 10, &roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002131 if (ret < 0)
2132 {
2133 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002134 kstrtou8 fails */
Srinivas Girigowdade697412013-02-14 16:31:48 -08002135 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002136 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdade697412013-02-14 16:31:48 -08002137 __func__,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002138 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2139 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002140 ret = -EINVAL;
2141 goto exit;
2142 }
2143
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002144 if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) ||
2145 (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)))
Srinivas Girigowdade697412013-02-14 16:31:48 -08002146 {
2147 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002148 "Roam scan period value %d is out of range"
2149 " (Min: %d Max: %d)", roamScanPeriod,
Srinivas Girigowdab8edd1e2013-03-19 11:42:08 -07002150 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000),
2151 (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002152 ret = -EINVAL;
2153 goto exit;
2154 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002155 neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002156
2157 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2158 "%s: Received Command to Set roam scan period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002159 " (Empty Scan refresh period) = %d", __func__, roamScanPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002160
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002161 pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod;
2162 sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002163 }
2164 else if (strncmp(command, "GETROAMSCANPERIOD", 17) == 0)
2165 {
2166 tANI_U16 nEmptyScanRefreshPeriod = sme_getEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2167 char extra[32];
2168 tANI_U8 len = 0;
2169
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002170 len = scnprintf(extra, sizeof(extra), "%s %d",
2171 "GETROAMSCANPERIOD", (nEmptyScanRefreshPeriod/1000));
Srinivas Girigowdade697412013-02-14 16:31:48 -08002172 /* Returned value is in units of seconds */
2173 if (copy_to_user(priv_data.buf, &extra, len + 1))
2174 {
2175 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2176 "%s: failed to copy data to user buffer", __func__);
2177 ret = -EFAULT;
2178 goto exit;
2179 }
2180 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002181 else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0)
2182 {
2183 tANI_U8 *value = command;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002184 tANI_U8 roamScanRefreshPeriod = 0;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002185 tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002186
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002187 /* input refresh period is in terms of seconds */
2188 /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD<delimiter> */
2189 value = value + 25;
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002190
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002191 /* Convert the value from ascii to integer */
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002192 ret = kstrtou8(value, 10, &roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002193 if (ret < 0)
2194 {
2195 /* If the input value is greater than max value of datatype, then also
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002196 kstrtou8 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002197 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002198 "%s: kstrtou8 failed Input value may be out of range[%d - %d]",
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002199 __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002200 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2201 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2202 ret = -EINVAL;
2203 goto exit;
2204 }
2205
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002206 if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) ||
2207 (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)))
2208 {
2209 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2210 "Neighbor scan results refresh period value %d is out of range"
2211 " (Min: %d Max: %d)", roamScanRefreshPeriod,
2212 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000),
2213 (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000));
2214 ret = -EINVAL;
2215 goto exit;
2216 }
2217 neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000;
2218
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002219 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2220 "%s: Received Command to Set roam scan refresh period"
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002221 " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002222
2223 pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod;
2224 sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod);
2225 }
2226 else if (strncmp(command, "GETROAMSCANREFRESHPERIOD", 24) == 0)
2227 {
2228 tANI_U16 value = sme_getNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal));
2229 char extra[32];
2230 tANI_U8 len = 0;
2231
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002232 len = scnprintf(extra, sizeof(extra), "%s %d",
2233 "GETROAMSCANREFRESHPERIOD", (value/1000));
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002234 /* Returned value is in units of seconds */
2235 if (copy_to_user(priv_data.buf, &extra, len + 1))
2236 {
2237 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2238 "%s: failed to copy data to user buffer", __func__);
2239 ret = -EFAULT;
2240 goto exit;
2241 }
2242 }
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002243#ifdef FEATURE_WLAN_LFR
2244 /* SETROAMMODE */
2245 else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0)
2246 {
2247 tANI_U8 *value = command;
2248 tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
2249
2250 /* Move pointer to ahead of SETROAMMODE<delimiter> */
2251 value = value + SIZE_OF_SETROAMMODE + 1;
2252
2253 /* Convert the value from ascii to integer */
2254 ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode);
2255 if (ret < 0)
2256 {
2257 /* If the input value is greater than max value of datatype, then also
2258 kstrtou8 fails */
2259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2260 "%s: kstrtou8 failed range [%d - %d]", __func__,
2261 CFG_LFR_FEATURE_ENABLED_MIN,
2262 CFG_LFR_FEATURE_ENABLED_MAX);
2263 ret = -EINVAL;
2264 goto exit;
2265 }
2266 if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
2267 (roamMode > CFG_LFR_FEATURE_ENABLED_MAX))
2268 {
2269 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2270 "Roam Mode value %d is out of range"
2271 " (Min: %d Max: %d)", roamMode,
2272 CFG_LFR_FEATURE_ENABLED_MIN,
2273 CFG_LFR_FEATURE_ENABLED_MAX);
2274 ret = -EINVAL;
2275 goto exit;
2276 }
2277
2278 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2279 "%s: Received Command to Set Roam Mode = %d", __func__, roamMode);
2280 /*
2281 * Note that
2282 * SETROAMMODE 0 is to enable LFR while
2283 * SETROAMMODE 1 is to disable LFR, but
2284 * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable.
2285 * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled.
2286 */
2287 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2288 roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */
2289 else
2290 roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */
2291
2292 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode;
2293 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode);
2294 }
2295 /* GETROAMMODE */
2296 else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0)
2297 {
2298 tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2299 char extra[32];
2300 tANI_U8 len = 0;
2301
2302 /*
2303 * roamMode value shall be inverted because the sementics is different.
2304 */
2305 if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode)
2306 roamMode = CFG_LFR_FEATURE_ENABLED_MAX;
2307 else
2308 roamMode = CFG_LFR_FEATURE_ENABLED_MIN;
2309
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002310 len = scnprintf(extra, sizeof(extra), "%s %d", command, roamMode);
Varun Reddy Yeturu6d99ac82013-05-08 14:15:35 -07002311 if (copy_to_user(priv_data.buf, &extra, len + 1))
2312 {
2313 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2314 "%s: failed to copy data to user buffer", __func__);
2315 ret = -EFAULT;
2316 goto exit;
2317 }
2318 }
2319#endif
Srinivas Girigowdade697412013-02-14 16:31:48 -08002320#endif
2321#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2322 else if (strncmp(command, "SETROAMDELTA", 12) == 0)
2323 {
2324 tANI_U8 *value = command;
2325 tANI_U8 roamRssiDiff = CFG_ROAM_RSSI_DIFF_DEFAULT;
2326
2327 /* Move pointer to ahead of SETROAMDELTA<delimiter> */
2328 value = value + 13;
2329 /* Convert the value from ascii to integer */
2330 ret = kstrtou8(value, 10, &roamRssiDiff);
2331 if (ret < 0)
2332 {
2333 /* If the input value is greater than max value of datatype, then also
2334 kstrtou8 fails */
2335 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2336 "%s: kstrtou8 failed range [%d - %d]", __func__,
2337 CFG_ROAM_RSSI_DIFF_MIN,
2338 CFG_ROAM_RSSI_DIFF_MAX);
2339 ret = -EINVAL;
2340 goto exit;
2341 }
2342
2343 if ((roamRssiDiff < CFG_ROAM_RSSI_DIFF_MIN) ||
2344 (roamRssiDiff > CFG_ROAM_RSSI_DIFF_MAX))
2345 {
2346 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2347 "Roam rssi diff value %d is out of range"
2348 " (Min: %d Max: %d)", roamRssiDiff,
2349 CFG_ROAM_RSSI_DIFF_MIN,
2350 CFG_ROAM_RSSI_DIFF_MAX);
2351 ret = -EINVAL;
2352 goto exit;
2353 }
2354
2355 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2356 "%s: Received Command to Set roam rssi diff = %d", __func__, roamRssiDiff);
2357
2358 pHddCtx->cfg_ini->RoamRssiDiff = roamRssiDiff;
2359 sme_UpdateRoamRssiDiff((tHalHandle)(pHddCtx->hHal), roamRssiDiff);
2360 }
2361 else if (strncmp(priv_data.buf, "GETROAMDELTA", 12) == 0)
2362 {
2363 tANI_U8 roamRssiDiff = sme_getRoamRssiDiff((tHalHandle)(pHddCtx->hHal));
2364 char extra[32];
2365 tANI_U8 len = 0;
2366
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002367 len = scnprintf(extra, sizeof(extra), "%s %d",
2368 command, roamRssiDiff);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002369 if (copy_to_user(priv_data.buf, &extra, len + 1))
2370 {
2371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2372 "%s: failed to copy data to user buffer", __func__);
2373 ret = -EFAULT;
2374 goto exit;
2375 }
2376 }
2377#endif
2378#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
2379 else if (strncmp(command, "GETBAND", 7) == 0)
2380 {
2381 int band = -1;
2382 char extra[32];
2383 tANI_U8 len = 0;
2384 hdd_getBand_helper(pHddCtx, &band);
2385
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002386 len = scnprintf(extra, sizeof(extra), "%s %d", command, band);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002387 if (copy_to_user(priv_data.buf, &extra, len + 1))
2388 {
2389 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2390 "%s: failed to copy data to user buffer", __func__);
2391 ret = -EFAULT;
2392 goto exit;
2393 }
2394 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08002395 else if (strncmp(command, "SETROAMSCANCHANNELS", 19) == 0)
2396 {
2397 tANI_U8 *value = command;
2398 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2399 tANI_U8 numChannels = 0;
2400 eHalStatus status = eHAL_STATUS_SUCCESS;
2401
2402 status = hdd_parse_channellist(value, ChannelList, &numChannels);
2403 if (eHAL_STATUS_SUCCESS != status)
2404 {
2405 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2406 "%s: Failed to parse channel list information", __func__);
2407 ret = -EINVAL;
2408 goto exit;
2409 }
2410
2411 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
2412 {
2413 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2414 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
2415 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
2416 ret = -EINVAL;
2417 goto exit;
2418 }
2419 status = sme_ChangeRoamScanChannelList((tHalHandle)(pHddCtx->hHal), ChannelList,
2420 numChannels);
2421 if (eHAL_STATUS_SUCCESS != status)
2422 {
2423 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2424 "%s: Failed to update channel list information", __func__);
2425 ret = -EINVAL;
2426 goto exit;
2427 }
2428 }
2429 else if (strncmp(command, "GETROAMSCANCHANNELS", 19) == 0)
2430 {
2431 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
2432 tANI_U8 numChannels = 0;
Jeff Johnson51b67782013-04-05 12:35:41 -07002433 tANI_U8 j = 0;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002434 char extra[128] = {0};
Jeff Johnson51b67782013-04-05 12:35:41 -07002435 int len;
Srinivas Girigowdade697412013-02-14 16:31:48 -08002436
2437 if (eHAL_STATUS_SUCCESS != sme_getRoamScanChannelList( (tHalHandle)(pHddCtx->hHal),
2438 ChannelList, &numChannels ))
2439 {
2440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
2441 "%s: failed to get roam scan channel list", __func__);
2442 ret = -EFAULT;
2443 goto exit;
2444 }
2445 /* output channel list is of the format
2446 [Number of roam scan channels][Channel1][Channel2]... */
2447 /* copy the number of channels in the 0th index */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002448 len = scnprintf(extra, sizeof(extra), "%s %d", command, numChannels);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002449 for (j = 0; (j < numChannels); j++)
2450 {
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002451 len += scnprintf(extra + len, sizeof(extra) - len, " %d",
2452 ChannelList[j]);
Srinivas Girigowdade697412013-02-14 16:31:48 -08002453 }
2454
2455 if (copy_to_user(priv_data.buf, &extra, len + 1))
2456 {
2457 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2458 "%s: failed to copy data to user buffer", __func__);
2459 ret = -EFAULT;
2460 goto exit;
2461 }
2462 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002463 else if (strncmp(command, "GETCCXMODE", 10) == 0)
2464 {
2465 tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2466 char extra[32];
2467 tANI_U8 len = 0;
2468
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002469 /* Check if the features OKC/CCX/11R are supported simultaneously,
2470 then this operation is not permitted (return FAILURE) */
2471 if (ccxMode &&
2472 hdd_is_okc_mode_enabled(pHddCtx) &&
2473 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2474 {
2475 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2476 "%s: OKC/CCX/11R are supported simultaneously"
2477 " hence this operation is not permitted!", __func__);
2478 ret = -EPERM;
2479 goto exit;
2480 }
2481
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002482 len = scnprintf(extra, sizeof(extra), "%s %d",
2483 "GETCCXMODE", ccxMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002484 if (copy_to_user(priv_data.buf, &extra, len + 1))
2485 {
2486 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2487 "%s: failed to copy data to user buffer", __func__);
2488 ret = -EFAULT;
2489 goto exit;
2490 }
2491 }
2492 else if (strncmp(command, "GETOKCMODE", 10) == 0)
2493 {
2494 tANI_BOOLEAN okcMode = hdd_is_okc_mode_enabled(pHddCtx);
2495 char extra[32];
2496 tANI_U8 len = 0;
2497
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07002498 /* Check if the features OKC/CCX/11R are supported simultaneously,
2499 then this operation is not permitted (return FAILURE) */
2500 if (okcMode &&
2501 sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
2502 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
2503 {
2504 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
2505 "%s: OKC/CCX/11R are supported simultaneously"
2506 " hence this operation is not permitted!", __func__);
2507 ret = -EPERM;
2508 goto exit;
2509 }
2510
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002511 len = scnprintf(extra, sizeof(extra), "%s %d",
2512 "GETOKCMODE", okcMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002513 if (copy_to_user(priv_data.buf, &extra, len + 1))
2514 {
2515 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2516 "%s: failed to copy data to user buffer", __func__);
2517 ret = -EFAULT;
2518 goto exit;
2519 }
2520 }
Srinivas Girigowdacb4c6412013-07-02 10:19:12 -07002521 else if (strncmp(command, "GETFASTROAM", 11) == 0)
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002522 {
2523 tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2524 char extra[32];
2525 tANI_U8 len = 0;
2526
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002527 len = scnprintf(extra, sizeof(extra), "%s %d",
2528 "GETFASTROAM", lfrMode);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002529 if (copy_to_user(priv_data.buf, &extra, len + 1))
2530 {
2531 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2532 "%s: failed to copy data to user buffer", __func__);
2533 ret = -EFAULT;
2534 goto exit;
2535 }
2536 }
2537 else if (strncmp(command, "GETFASTTRANSITION", 17) == 0)
2538 {
2539 tANI_BOOLEAN ft = sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal));
2540 char extra[32];
2541 tANI_U8 len = 0;
2542
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002543 len = scnprintf(extra, sizeof(extra), "%s %d",
2544 "GETFASTTRANSITION", ft);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002545 if (copy_to_user(priv_data.buf, &extra, len + 1))
2546 {
2547 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2548 "%s: failed to copy data to user buffer", __func__);
2549 ret = -EFAULT;
2550 goto exit;
2551 }
2552 }
2553 else if (strncmp(command, "SETROAMSCANCHANNELMINTIME", 25) == 0)
2554 {
2555 tANI_U8 *value = command;
2556 tANI_U8 minTime = CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_DEFAULT;
2557
2558 /* Move pointer to ahead of SETROAMSCANCHANNELMINTIME<delimiter> */
2559 value = value + 26;
2560 /* Convert the value from ascii to integer */
2561 ret = kstrtou8(value, 10, &minTime);
2562 if (ret < 0)
2563 {
2564 /* If the input value is greater than max value of datatype, then also
2565 kstrtou8 fails */
2566 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2567 "%s: kstrtou8 failed range [%d - %d]", __func__,
2568 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2569 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2570 ret = -EINVAL;
2571 goto exit;
2572 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002573 if ((minTime < CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN) ||
2574 (minTime > CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX))
2575 {
2576 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2577 "scan min channel time value %d is out of range"
2578 " (Min: %d Max: %d)", minTime,
2579 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MIN,
2580 CFG_NEIGHBOR_SCAN_MIN_CHAN_TIME_MAX);
2581 ret = -EINVAL;
2582 goto exit;
2583 }
2584
2585 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2586 "%s: Received Command to change channel min time = %d", __func__, minTime);
2587
2588 pHddCtx->cfg_ini->nNeighborScanMinChanTime = minTime;
2589 sme_setNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal), minTime);
2590 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002591 else if (strncmp(command, "SENDACTIONFRAME", 15) == 0)
2592 {
2593 tANI_U8 *value = command;
2594 tANI_U8 channel = 0;
2595 tANI_U8 dwellTime = 0;
2596 tANI_U8 bufLen = 0;
2597 tANI_U8 *buf = NULL;
2598 tSirMacAddr targetApBssid;
2599 eHalStatus status = eHAL_STATUS_SUCCESS;
2600 struct ieee80211_channel chan;
2601 tANI_U8 finalLen = 0;
2602 tANI_U8 *finalBuf = NULL;
2603 tANI_U8 temp = 0;
2604 u64 cookie;
2605 hdd_station_ctx_t *pHddStaCtx = NULL;
2606 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
2607
2608 /* if not associated, no need to send action frame */
2609 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
2610 {
2611 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
2612 ret = -EINVAL;
2613 goto exit;
2614 }
2615
2616 status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel,
2617 &dwellTime, &buf, &bufLen);
2618 if (eHAL_STATUS_SUCCESS != status)
2619 {
2620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2621 "%s: Failed to parse send action frame data", __func__);
2622 ret = -EINVAL;
2623 goto exit;
2624 }
2625
2626 /* if the target bssid is different from currently associated AP,
2627 then no need to send action frame */
2628 if (VOS_TRUE != vos_mem_compare(targetApBssid,
2629 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
2630 {
2631 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__);
2632 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002633 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002634 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002635 goto exit;
2636 }
2637
2638 /* if the channel number is different from operating channel then
2639 no need to send action frame */
2640 if (channel != pHddStaCtx->conn_info.operationChannel)
2641 {
2642 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2643 "%s: channel(%d) is different from operating channel(%d)",
2644 __func__, channel, pHddStaCtx->conn_info.operationChannel);
2645 ret = -EINVAL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002646 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002647 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002648 goto exit;
2649 }
2650 chan.center_freq = sme_ChnToFreq(channel);
2651
2652 finalLen = bufLen + 24;
2653 finalBuf = vos_mem_malloc(finalLen);
2654 if (NULL == finalBuf)
2655 {
2656 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__);
2657 ret = -ENOMEM;
Jeff Johnson11c33152013-04-16 17:52:40 -07002658 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002659 buf = NULL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002660 goto exit;
2661 }
2662 vos_mem_zero(finalBuf, finalLen);
2663
2664 /* Fill subtype */
2665 temp = SIR_MAC_MGMT_ACTION << 4;
2666 vos_mem_copy(finalBuf + 0, &temp, sizeof(temp));
2667
2668 /* Fill type */
2669 temp = SIR_MAC_MGMT_FRAME;
2670 vos_mem_copy(finalBuf + 2, &temp, sizeof(temp));
2671
2672 /* Fill destination address (bssid of the AP) */
2673 vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid));
2674
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002675 /* Fill source address (STA mac address) */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002676 vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes));
2677
Srinivas Girigowdab27c0192013-06-03 10:19:56 -07002678 /* Fill BSSID (AP mac address) */
2679 vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid));
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002680
2681 /* Fill received buffer from 24th address */
2682 vos_mem_copy(finalBuf + 24, buf, bufLen);
2683
Jeff Johnson11c33152013-04-16 17:52:40 -07002684 /* done with the parsed buffer */
2685 vos_mem_free(buf);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08002686 buf = NULL;
Jeff Johnson11c33152013-04-16 17:52:40 -07002687
Yue Maf49ba872013-08-19 12:04:25 -07002688 wlan_hdd_action( NULL,
2689#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0))
2690 &(pAdapter->wdev),
2691#else
2692 dev,
2693#endif
2694 &chan, 0,
2695#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0))
2696 NL80211_CHAN_HT20, 1,
2697#endif
2698 dwellTime, finalBuf, finalLen, 1,
Srinivas Girigowda100eb322013-03-15 16:48:20 -07002699 1, &cookie );
2700 vos_mem_free(finalBuf);
2701 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002702 else if (strncmp(command, "GETROAMSCANCHANNELMINTIME", 25) == 0)
2703 {
2704 tANI_U16 val = sme_getNeighborScanMinChanTime((tHalHandle)(pHddCtx->hHal));
2705 char extra[32];
2706 tANI_U8 len = 0;
2707
2708 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002709 len = scnprintf(extra, sizeof(extra), "%s %d",
2710 "GETROAMSCANCHANNELMINTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002711 if (copy_to_user(priv_data.buf, &extra, len + 1))
2712 {
2713 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2714 "%s: failed to copy data to user buffer", __func__);
2715 ret = -EFAULT;
2716 goto exit;
2717 }
2718 }
2719 else if (strncmp(command, "SETSCANCHANNELTIME", 18) == 0)
2720 {
2721 tANI_U8 *value = command;
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002722 tANI_U16 maxTime = CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT;
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002723
2724 /* Move pointer to ahead of SETSCANCHANNELTIME<delimiter> */
2725 value = value + 19;
2726 /* Convert the value from ascii to integer */
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002727 ret = kstrtou16(value, 10, &maxTime);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002728 if (ret < 0)
2729 {
2730 /* If the input value is greater than max value of datatype, then also
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002731 kstrtou16 fails */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002732 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
Varun Reddy Yeturu3885a662013-06-19 07:10:37 -07002733 "%s: kstrtou16 failed range [%d - %d]", __func__,
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002734 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2735 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2736 ret = -EINVAL;
2737 goto exit;
2738 }
2739
2740 if ((maxTime < CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN) ||
2741 (maxTime > CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX))
2742 {
2743 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2744 "lfr mode value %d is out of range"
2745 " (Min: %d Max: %d)", maxTime,
2746 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MIN,
2747 CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_MAX);
2748 ret = -EINVAL;
2749 goto exit;
2750 }
2751
2752 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2753 "%s: Received Command to change channel max time = %d", __func__, maxTime);
2754
2755 pHddCtx->cfg_ini->nNeighborScanMaxChanTime = maxTime;
2756 sme_setNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal), maxTime);
2757 }
2758 else if (strncmp(command, "GETSCANCHANNELTIME", 18) == 0)
2759 {
2760 tANI_U16 val = sme_getNeighborScanMaxChanTime((tHalHandle)(pHddCtx->hHal));
2761 char extra[32];
2762 tANI_U8 len = 0;
2763
2764 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002765 len = scnprintf(extra, sizeof(extra), "%s %d",
2766 "GETSCANCHANNELTIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002767 if (copy_to_user(priv_data.buf, &extra, len + 1))
2768 {
2769 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2770 "%s: failed to copy data to user buffer", __func__);
2771 ret = -EFAULT;
2772 goto exit;
2773 }
2774 }
2775 else if (strncmp(command, "SETSCANHOMETIME", 15) == 0)
2776 {
2777 tANI_U8 *value = command;
2778 tANI_U16 val = CFG_NEIGHBOR_SCAN_TIMER_PERIOD_DEFAULT;
2779
2780 /* Move pointer to ahead of SETSCANHOMETIME<delimiter> */
2781 value = value + 16;
2782 /* Convert the value from ascii to integer */
2783 ret = kstrtou16(value, 10, &val);
2784 if (ret < 0)
2785 {
2786 /* If the input value is greater than max value of datatype, then also
2787 kstrtou16 fails */
2788 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2789 "%s: kstrtou16 failed range [%d - %d]", __func__,
2790 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2791 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2792 ret = -EINVAL;
2793 goto exit;
2794 }
2795
2796 if ((val < CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN) ||
2797 (val > CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX))
2798 {
2799 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2800 "scan home time value %d is out of range"
2801 " (Min: %d Max: %d)", val,
2802 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MIN,
2803 CFG_NEIGHBOR_SCAN_TIMER_PERIOD_MAX);
2804 ret = -EINVAL;
2805 goto exit;
2806 }
2807
2808 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2809 "%s: Received Command to change scan home time = %d", __func__, val);
2810
2811 pHddCtx->cfg_ini->nNeighborScanPeriod = val;
2812 sme_setNeighborScanPeriod((tHalHandle)(pHddCtx->hHal), val);
2813 }
2814 else if (strncmp(command, "GETSCANHOMETIME", 15) == 0)
2815 {
2816 tANI_U16 val = sme_getNeighborScanPeriod((tHalHandle)(pHddCtx->hHal));
2817 char extra[32];
2818 tANI_U8 len = 0;
2819
2820 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002821 len = scnprintf(extra, sizeof(extra), "%s %d",
2822 "GETSCANHOMETIME", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002823 if (copy_to_user(priv_data.buf, &extra, len + 1))
2824 {
2825 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2826 "%s: failed to copy data to user buffer", __func__);
2827 ret = -EFAULT;
2828 goto exit;
2829 }
2830 }
2831 else if (strncmp(command, "SETROAMINTRABAND", 16) == 0)
2832 {
2833 tANI_U8 *value = command;
2834 tANI_U8 val = CFG_ROAM_INTRA_BAND_DEFAULT;
2835
2836 /* Move pointer to ahead of SETROAMINTRABAND<delimiter> */
2837 value = value + 17;
2838 /* Convert the value from ascii to integer */
2839 ret = kstrtou8(value, 10, &val);
2840 if (ret < 0)
2841 {
2842 /* If the input value is greater than max value of datatype, then also
2843 kstrtou8 fails */
2844 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2845 "%s: kstrtou8 failed range [%d - %d]", __func__,
2846 CFG_ROAM_INTRA_BAND_MIN,
2847 CFG_ROAM_INTRA_BAND_MAX);
2848 ret = -EINVAL;
2849 goto exit;
2850 }
2851
2852 if ((val < CFG_ROAM_INTRA_BAND_MIN) ||
2853 (val > CFG_ROAM_INTRA_BAND_MAX))
2854 {
2855 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2856 "intra band mode value %d is out of range"
2857 " (Min: %d Max: %d)", val,
2858 CFG_ROAM_INTRA_BAND_MIN,
2859 CFG_ROAM_INTRA_BAND_MAX);
2860 ret = -EINVAL;
2861 goto exit;
2862 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002863 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2864 "%s: Received Command to change intra band = %d", __func__, val);
2865
2866 pHddCtx->cfg_ini->nRoamIntraBand = val;
2867 sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), val);
2868 }
2869 else if (strncmp(command, "GETROAMINTRABAND", 16) == 0)
2870 {
2871 tANI_U16 val = sme_getRoamIntraBand((tHalHandle)(pHddCtx->hHal));
2872 char extra[32];
2873 tANI_U8 len = 0;
2874
2875 /* value is interms of msec */
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002876 len = scnprintf(extra, sizeof(extra), "%s %d",
2877 "GETROAMINTRABAND", val);
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07002878 if (copy_to_user(priv_data.buf, &extra, len + 1))
2879 {
2880 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2881 "%s: failed to copy data to user buffer", __func__);
2882 ret = -EFAULT;
2883 goto exit;
2884 }
2885 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002886 else if (strncmp(command, "SETSCANNPROBES", 14) == 0)
2887 {
2888 tANI_U8 *value = command;
2889 tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT;
2890
2891 /* Move pointer to ahead of SETSCANNPROBES<delimiter> */
2892 value = value + 15;
2893 /* Convert the value from ascii to integer */
2894 ret = kstrtou8(value, 10, &nProbes);
2895 if (ret < 0)
2896 {
2897 /* If the input value is greater than max value of datatype, then also
2898 kstrtou8 fails */
2899 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2900 "%s: kstrtou8 failed range [%d - %d]", __func__,
2901 CFG_ROAM_SCAN_N_PROBES_MIN,
2902 CFG_ROAM_SCAN_N_PROBES_MAX);
2903 ret = -EINVAL;
2904 goto exit;
2905 }
2906
2907 if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) ||
2908 (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX))
2909 {
2910 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2911 "NProbes value %d is out of range"
2912 " (Min: %d Max: %d)", nProbes,
2913 CFG_ROAM_SCAN_N_PROBES_MIN,
2914 CFG_ROAM_SCAN_N_PROBES_MAX);
2915 ret = -EINVAL;
2916 goto exit;
2917 }
2918
2919 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2920 "%s: Received Command to Set nProbes = %d", __func__, nProbes);
2921
2922 pHddCtx->cfg_ini->nProbes = nProbes;
2923 sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes);
2924 }
2925 else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0)
2926 {
2927 tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal));
2928 char extra[32];
2929 tANI_U8 len = 0;
2930
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002931 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002932 if (copy_to_user(priv_data.buf, &extra, len + 1))
2933 {
2934 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2935 "%s: failed to copy data to user buffer", __func__);
2936 ret = -EFAULT;
2937 goto exit;
2938 }
2939 }
2940 else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0)
2941 {
2942 tANI_U8 *value = command;
2943 tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT;
2944
2945 /* Move pointer to ahead of SETSCANHOMEAWAYTIME<delimiter> */
2946 /* input value is in units of msec */
2947 value = value + 20;
2948 /* Convert the value from ascii to integer */
2949 ret = kstrtou16(value, 10, &homeAwayTime);
2950 if (ret < 0)
2951 {
2952 /* If the input value is greater than max value of datatype, then also
2953 kstrtou8 fails */
2954 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2955 "%s: kstrtou8 failed range [%d - %d]", __func__,
2956 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2957 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2958 ret = -EINVAL;
2959 goto exit;
2960 }
2961
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002962 if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) ||
2963 (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX))
2964 {
2965 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2966 "homeAwayTime value %d is out of range"
2967 " (Min: %d Max: %d)", homeAwayTime,
2968 CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN,
2969 CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX);
2970 ret = -EINVAL;
2971 goto exit;
2972 }
2973
2974 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
2975 "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime);
Srinivas Girigowda6cf0b822013-06-27 14:00:20 -07002976 if (pHddCtx->cfg_ini->nRoamScanHomeAwayTime != homeAwayTime)
2977 {
2978 pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime;
2979 sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime, eANI_BOOLEAN_TRUE);
2980 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002981 }
2982 else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0)
2983 {
2984 tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal));
2985 char extra[32];
2986 tANI_U8 len = 0;
2987
Sameer Thalappilb0a30232013-09-27 15:37:48 -07002988 len = scnprintf(extra, sizeof(extra), "%s %d", command, val);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07002989 if (copy_to_user(priv_data.buf, &extra, len + 1))
2990 {
2991 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
2992 "%s: failed to copy data to user buffer", __func__);
2993 ret = -EFAULT;
2994 goto exit;
2995 }
2996 }
2997 else if (strncmp(command, "REASSOC", 7) == 0)
2998 {
2999 tANI_U8 *value = command;
3000 tANI_U8 channel = 0;
3001 tSirMacAddr targetApBssid;
3002 eHalStatus status = eHAL_STATUS_SUCCESS;
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003003#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3004 tCsrHandoffRequest handoffInfo;
3005#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003006 hdd_station_ctx_t *pHddStaCtx = NULL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003007 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3008
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003009 /* if not associated, no need to proceed with reassoc */
3010 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3011 {
3012 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3013 ret = -EINVAL;
3014 goto exit;
3015 }
3016
3017 status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel);
3018 if (eHAL_STATUS_SUCCESS != status)
3019 {
3020 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3021 "%s: Failed to parse reassoc command data", __func__);
3022 ret = -EINVAL;
3023 goto exit;
3024 }
3025
3026 /* if the target bssid is same as currently associated AP,
3027 then no need to proceed with reassoc */
3028 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3029 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3030 {
3031 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__);
3032 ret = -EINVAL;
3033 goto exit;
3034 }
3035
3036 /* Check channel number is a valid channel number */
3037 if(VOS_STATUS_SUCCESS !=
3038 wlan_hdd_validate_operation_channel(pAdapter, channel))
3039 {
3040 hddLog(VOS_TRACE_LEVEL_ERROR,
Arif Hussain6d2a3322013-11-17 19:50:10 -08003041 "%s: Invalid Channel [%d]", __func__, channel);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003042 return -EINVAL;
3043 }
3044
3045 /* Proceed with reassoc */
Varun Reddy Yeturucc661d22013-05-20 11:47:10 -07003046#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
3047 handoffInfo.channel = channel;
3048 vos_mem_copy(handoffInfo.bssid, targetApBssid, sizeof(tSirMacAddr));
3049 sme_HandoffRequest(pHddCtx->hHal, &handoffInfo);
3050#endif
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07003051 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003052 else if (strncmp(command, "SETWESMODE", 10) == 0)
3053 {
3054 tANI_U8 *value = command;
3055 tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT;
3056
3057 /* Move pointer to ahead of SETWESMODE<delimiter> */
3058 value = value + 11;
3059 /* Convert the value from ascii to integer */
3060 ret = kstrtou8(value, 10, &wesMode);
3061 if (ret < 0)
3062 {
3063 /* If the input value is greater than max value of datatype, then also
3064 kstrtou8 fails */
3065 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3066 "%s: kstrtou8 failed range [%d - %d]", __func__,
3067 CFG_ENABLE_WES_MODE_NAME_MIN,
3068 CFG_ENABLE_WES_MODE_NAME_MAX);
3069 ret = -EINVAL;
3070 goto exit;
3071 }
3072
3073 if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) ||
3074 (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX))
3075 {
3076 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3077 "WES Mode value %d is out of range"
3078 " (Min: %d Max: %d)", wesMode,
3079 CFG_ENABLE_WES_MODE_NAME_MIN,
3080 CFG_ENABLE_WES_MODE_NAME_MAX);
3081 ret = -EINVAL;
3082 goto exit;
3083 }
3084 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3085 "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode);
3086
3087 pHddCtx->cfg_ini->isWESModeEnabled = wesMode;
3088 sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode);
3089 }
3090 else if (strncmp(priv_data.buf, "GETWESMODE", 10) == 0)
3091 {
3092 tANI_BOOLEAN wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal));
3093 char extra[32];
3094 tANI_U8 len = 0;
3095
Arif Hussain826d9412013-11-12 16:44:54 -08003096 len = scnprintf(extra, sizeof(extra), "%s %d", command, wesMode);
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003097 if (copy_to_user(priv_data.buf, &extra, len + 1))
3098 {
3099 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3100 "%s: failed to copy data to user buffer", __func__);
3101 ret = -EFAULT;
3102 goto exit;
3103 }
3104 }
3105#endif /* WLAN_FEATURE_VOWIFI_11R || FEATURE_WLAN_CCX || FEATURE_WLAN_LFR */
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003106#ifdef FEATURE_WLAN_LFR
3107 else if (strncmp(command, "SETFASTROAM", 11) == 0)
3108 {
3109 tANI_U8 *value = command;
3110 tANI_U8 lfrMode = CFG_LFR_FEATURE_ENABLED_DEFAULT;
3111
3112 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3113 value = value + 12;
3114 /* Convert the value from ascii to integer */
3115 ret = kstrtou8(value, 10, &lfrMode);
3116 if (ret < 0)
3117 {
3118 /* If the input value is greater than max value of datatype, then also
3119 kstrtou8 fails */
3120 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3121 "%s: kstrtou8 failed range [%d - %d]", __func__,
3122 CFG_LFR_FEATURE_ENABLED_MIN,
3123 CFG_LFR_FEATURE_ENABLED_MAX);
3124 ret = -EINVAL;
3125 goto exit;
3126 }
3127
3128 if ((lfrMode < CFG_LFR_FEATURE_ENABLED_MIN) ||
3129 (lfrMode > CFG_LFR_FEATURE_ENABLED_MAX))
3130 {
3131 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3132 "lfr mode value %d is out of range"
3133 " (Min: %d Max: %d)", lfrMode,
3134 CFG_LFR_FEATURE_ENABLED_MIN,
3135 CFG_LFR_FEATURE_ENABLED_MAX);
3136 ret = -EINVAL;
3137 goto exit;
3138 }
3139
3140 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3141 "%s: Received Command to change lfr mode = %d", __func__, lfrMode);
3142
3143 pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = lfrMode;
3144 sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), lfrMode);
3145 }
3146#endif
3147#ifdef WLAN_FEATURE_VOWIFI_11R
3148 else if (strncmp(command, "SETFASTTRANSITION", 17) == 0)
3149 {
3150 tANI_U8 *value = command;
3151 tANI_U8 ft = CFG_FAST_TRANSITION_ENABLED_NAME_DEFAULT;
3152
3153 /* Move pointer to ahead of SETFASTROAM<delimiter> */
3154 value = value + 18;
3155 /* Convert the value from ascii to integer */
3156 ret = kstrtou8(value, 10, &ft);
3157 if (ret < 0)
3158 {
3159 /* If the input value is greater than max value of datatype, then also
3160 kstrtou8 fails */
3161 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3162 "%s: kstrtou8 failed range [%d - %d]", __func__,
3163 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3164 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3165 ret = -EINVAL;
3166 goto exit;
3167 }
3168
3169 if ((ft < CFG_FAST_TRANSITION_ENABLED_NAME_MIN) ||
3170 (ft > CFG_FAST_TRANSITION_ENABLED_NAME_MAX))
3171 {
3172 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3173 "ft mode value %d is out of range"
3174 " (Min: %d Max: %d)", ft,
3175 CFG_FAST_TRANSITION_ENABLED_NAME_MIN,
3176 CFG_FAST_TRANSITION_ENABLED_NAME_MAX);
3177 ret = -EINVAL;
3178 goto exit;
3179 }
3180
3181 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3182 "%s: Received Command to change ft mode = %d", __func__, ft);
3183
3184 pHddCtx->cfg_ini->isFastTransitionEnabled = ft;
3185 sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), ft);
3186 }
Madan Mohan Koyyalamudi48101412013-09-11 23:09:37 +05303187
3188 else if (strncmp(command, "FASTREASSOC", 11) == 0)
3189 {
3190 tANI_U8 *value = command;
3191 tSirMacAddr targetApBssid;
3192 tANI_U8 trigger = 0;
3193 eHalStatus status = eHAL_STATUS_SUCCESS;
3194 hdd_station_ctx_t *pHddStaCtx = NULL;
3195 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3196
3197 /* if not associated, no need to proceed with reassoc */
3198 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3199 {
3200 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__);
3201 ret = -EINVAL;
3202 goto exit;
3203 }
3204
3205 status = hdd_parse_reassoc_command_data(value, targetApBssid, &trigger);
3206 if (eHAL_STATUS_SUCCESS != status)
3207 {
3208 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3209 "%s: Failed to parse reassoc command data", __func__);
3210 ret = -EINVAL;
3211 goto exit;
3212 }
3213
3214 /* if the target bssid is same as currently associated AP,
3215 then no need to proceed with reassoc */
3216 if (VOS_TRUE == vos_mem_compare(targetApBssid,
3217 pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr)))
3218 {
3219 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3220 "%s:11r Reassoc BSSID is same as currently associated AP bssid",
3221 __func__);
3222 ret = -EINVAL;
3223 goto exit;
3224 }
3225
3226 /* Proceed with scan/roam */
3227 smeIssueFastRoamNeighborAPEvent(WLAN_HDD_GET_HAL_CTX(pAdapter),
3228 &targetApBssid[0],
3229 (tSmeFastRoamTrigger)(trigger));
3230 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003231#endif
3232#ifdef FEATURE_WLAN_CCX
3233 else if (strncmp(command, "SETCCXMODE", 10) == 0)
3234 {
3235 tANI_U8 *value = command;
3236 tANI_U8 ccxMode = CFG_CCX_FEATURE_ENABLED_DEFAULT;
3237
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003238 /* Check if the features OKC/CCX/11R are supported simultaneously,
3239 then this operation is not permitted (return FAILURE) */
3240 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3241 hdd_is_okc_mode_enabled(pHddCtx) &&
3242 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3243 {
3244 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3245 "%s: OKC/CCX/11R are supported simultaneously"
3246 " hence this operation is not permitted!", __func__);
3247 ret = -EPERM;
3248 goto exit;
3249 }
3250
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003251 /* Move pointer to ahead of SETCCXMODE<delimiter> */
3252 value = value + 11;
3253 /* Convert the value from ascii to integer */
3254 ret = kstrtou8(value, 10, &ccxMode);
3255 if (ret < 0)
3256 {
3257 /* If the input value is greater than max value of datatype, then also
3258 kstrtou8 fails */
3259 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3260 "%s: kstrtou8 failed range [%d - %d]", __func__,
3261 CFG_CCX_FEATURE_ENABLED_MIN,
3262 CFG_CCX_FEATURE_ENABLED_MAX);
3263 ret = -EINVAL;
3264 goto exit;
3265 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003266 if ((ccxMode < CFG_CCX_FEATURE_ENABLED_MIN) ||
3267 (ccxMode > CFG_CCX_FEATURE_ENABLED_MAX))
3268 {
3269 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3270 "Ccx mode value %d is out of range"
3271 " (Min: %d Max: %d)", ccxMode,
3272 CFG_CCX_FEATURE_ENABLED_MIN,
3273 CFG_CCX_FEATURE_ENABLED_MAX);
3274 ret = -EINVAL;
3275 goto exit;
3276 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003277 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3278 "%s: Received Command to change ccx mode = %d", __func__, ccxMode);
3279
3280 pHddCtx->cfg_ini->isCcxIniFeatureEnabled = ccxMode;
3281 sme_UpdateIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal), ccxMode);
3282 }
3283#endif
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003284 else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0)
3285 {
3286 tANI_U8 *value = command;
3287 tANI_BOOLEAN roamScanControl = 0;
3288
3289 /* Move pointer to ahead of SETROAMSCANCONTROL<delimiter> */
3290 value = value + 19;
3291 /* Convert the value from ascii to integer */
3292 ret = kstrtou8(value, 10, &roamScanControl);
3293 if (ret < 0)
3294 {
3295 /* If the input value is greater than max value of datatype, then also
3296 kstrtou8 fails */
3297 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3298 "%s: kstrtou8 failed ", __func__);
3299 ret = -EINVAL;
3300 goto exit;
3301 }
3302
3303 if (0 != roamScanControl)
3304 {
3305 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3306 "roam scan control invalid value = %d",
3307 roamScanControl);
3308 ret = -EINVAL;
3309 goto exit;
3310 }
3311 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3312 "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl);
3313
3314 sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl);
3315 }
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003316#ifdef FEATURE_WLAN_OKC
3317 else if (strncmp(command, "SETOKCMODE", 10) == 0)
3318 {
3319 tANI_U8 *value = command;
3320 tANI_U8 okcMode = CFG_OKC_FEATURE_ENABLED_DEFAULT;
3321
Srinivas Girigowdac6745a32013-07-15 19:19:10 -07003322 /* Check if the features OKC/CCX/11R are supported simultaneously,
3323 then this operation is not permitted (return FAILURE) */
3324 if (sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)) &&
3325 hdd_is_okc_mode_enabled(pHddCtx) &&
3326 sme_getIsFtFeatureEnabled((tHalHandle)(pHddCtx->hHal)))
3327 {
3328 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
3329 "%s: OKC/CCX/11R are supported simultaneously"
3330 " hence this operation is not permitted!", __func__);
3331 ret = -EPERM;
3332 goto exit;
3333 }
3334
Srinivas Girigowdabbd16eb2013-03-21 12:34:46 -07003335 /* Move pointer to ahead of SETOKCMODE<delimiter> */
3336 value = value + 11;
3337 /* Convert the value from ascii to integer */
3338 ret = kstrtou8(value, 10, &okcMode);
3339 if (ret < 0)
3340 {
3341 /* If the input value is greater than max value of datatype, then also
3342 kstrtou8 fails */
3343 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3344 "%s: kstrtou8 failed range [%d - %d]", __func__,
3345 CFG_OKC_FEATURE_ENABLED_MIN,
3346 CFG_OKC_FEATURE_ENABLED_MAX);
3347 ret = -EINVAL;
3348 goto exit;
3349 }
3350
3351 if ((okcMode < CFG_OKC_FEATURE_ENABLED_MIN) ||
3352 (okcMode > CFG_OKC_FEATURE_ENABLED_MAX))
3353 {
3354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3355 "Okc mode value %d is out of range"
3356 " (Min: %d Max: %d)", okcMode,
3357 CFG_OKC_FEATURE_ENABLED_MIN,
3358 CFG_OKC_FEATURE_ENABLED_MAX);
3359 ret = -EINVAL;
3360 goto exit;
3361 }
3362
3363 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3364 "%s: Received Command to change okc mode = %d", __func__, okcMode);
3365
3366 pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode;
3367 }
Srinivas Girigowdaad34ca92013-10-22 10:54:29 -07003368#endif /* FEATURE_WLAN_OKC */
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003369 else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0)
3370 {
3371 tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal));
3372 char extra[32];
3373 tANI_U8 len = 0;
3374
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003375 len = scnprintf(extra, sizeof(extra), "%s %d",
3376 command, roamScanControl);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07003377 if (copy_to_user(priv_data.buf, &extra, len + 1))
3378 {
3379 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3380 "%s: failed to copy data to user buffer", __func__);
3381 ret = -EFAULT;
3382 goto exit;
3383 }
3384 }
Gopichand Nakkala227c7f32013-06-26 22:44:57 +05303385#ifdef WLAN_FEATURE_PACKET_FILTERING
3386 else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0)
3387 {
3388 tANI_U8 filterType = 0;
3389 tANI_U8 *value = command;
3390
3391 /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6<delimiter> */
3392 value = value + 22;
3393
3394 /* Convert the value from ascii to integer */
3395 ret = kstrtou8(value, 10, &filterType);
3396 if (ret < 0)
3397 {
3398 /* If the input value is greater than max value of datatype,
3399 * then also kstrtou8 fails
3400 */
3401 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3402 "%s: kstrtou8 failed range ", __func__);
3403 ret = -EINVAL;
3404 goto exit;
3405 }
3406
3407 if (filterType != 0 && filterType != 1)
3408 {
3409 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3410 "%s: Accepted Values are 0 and 1 ", __func__);
3411 ret = -EINVAL;
3412 goto exit;
3413 }
3414 wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType,
3415 pAdapter->sessionId);
3416 }
3417#endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303418 else if (strncmp(command, "BTCOEXMODE", 10) == 0 )
3419 {
3420 char *dhcpPhase;
c_hpothu9b781ba2013-12-30 20:57:45 +05303421 dhcpPhase = command + 11;
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303422 if ('1' == *dhcpPhase)
3423 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303424 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu0b0cab72014-02-13 21:52:40 +05303425 FL("send DHCP START indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303426
3427 pHddCtx->btCoexModeSet = TRUE;
3428
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303429 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
c_hpothu0b0cab72014-02-13 21:52:40 +05303430 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303431 }
3432 else if ('2' == *dhcpPhase)
3433 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303434 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu0b0cab72014-02-13 21:52:40 +05303435 FL("send DHCP STOP indication"));
c_hpothu9b781ba2013-12-30 20:57:45 +05303436
3437 pHddCtx->btCoexModeSet = FALSE;
3438
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303439 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
c_hpothu0b0cab72014-02-13 21:52:40 +05303440 pAdapter->sessionId);
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303441 }
3442 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003443 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3444 {
3445 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3446 }
3447 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3448 {
3449 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3450 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303451 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3452 {
3453 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3454 char extra[32];
3455 tANI_U8 len = 0;
3456
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003457 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303458 (int)pCfg->nActiveMaxChnTime);
3459 if (copy_to_user(priv_data.buf, &extra, len + 1))
3460 {
3461 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3462 "%s: failed to copy data to user buffer", __func__);
3463 ret = -EFAULT;
3464 goto exit;
3465 }
3466 ret = len;
3467 }
3468 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3469 {
3470 tANI_U8 *value = command;
3471 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3472 int val = 0, temp;
3473
3474 value = value + 13;
3475 temp = kstrtou32(value, 10, &val);
3476 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3477 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3478 {
3479 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3480 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3481 ret = -EFAULT;
3482 goto exit;
3483 }
3484 pCfg->nActiveMaxChnTime = val;
3485 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003486 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3487 {
3488 tANI_U8 filterType = 0;
3489 tANI_U8 *value;
3490 value = command + 9;
3491
3492 /* Convert the value from ascii to integer */
3493 ret = kstrtou8(value, 10, &filterType);
3494 if (ret < 0)
3495 {
3496 /* If the input value is greater than max value of datatype,
3497 * then also kstrtou8 fails
3498 */
3499 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3500 "%s: kstrtou8 failed range ", __func__);
3501 ret = -EINVAL;
3502 goto exit;
3503 }
3504 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3505 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3506 {
3507 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3508 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3509 " 2-Sink ", __func__);
3510 ret = -EINVAL;
3511 goto exit;
3512 }
3513 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3514 pHddCtx->drvr_miracast = filterType;
3515 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3516 }
Leo Chang614d2072013-08-22 14:59:44 -07003517 else if (strncmp(command, "SETMCRATE", 9) == 0)
3518 {
Leo Chang614d2072013-08-22 14:59:44 -07003519 tANI_U8 *value = command;
3520 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003521 tSirRateUpdateInd *rateUpdate;
3522 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003523
3524 /* Only valid for SAP mode */
3525 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3526 {
3527 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3528 "%s: SAP mode is not running", __func__);
3529 ret = -EFAULT;
3530 goto exit;
3531 }
3532
3533 /* Move pointer to ahead of SETMCRATE<delimiter> */
3534 /* input value is in units of hundred kbps */
3535 value = value + 10;
3536 /* Convert the value from ascii to integer, decimal base */
3537 ret = kstrtouint(value, 10, &targetRate);
3538
Leo Chang1f98cbd2013-10-17 15:03:52 -07003539 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3540 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003541 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003542 hddLog(VOS_TRACE_LEVEL_ERROR,
3543 "%s: SETMCRATE indication alloc fail", __func__);
3544 ret = -EFAULT;
3545 goto exit;
3546 }
3547 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3548
3549 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3550 "MC Target rate %d", targetRate);
3551 /* Ignore unicast */
3552 rateUpdate->ucastDataRate = -1;
3553 rateUpdate->mcastDataRate24GHz = targetRate;
3554 rateUpdate->mcastDataRate5GHz = targetRate;
3555 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3556 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3557 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3558 if (eHAL_STATUS_SUCCESS != status)
3559 {
3560 hddLog(VOS_TRACE_LEVEL_ERROR,
3561 "%s: SET_MC_RATE failed", __func__);
3562 vos_mem_free(rateUpdate);
3563 ret = -EFAULT;
3564 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003565 }
3566 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303567#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003568 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303569 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003570 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303571 }
3572#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003573#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3574 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3575 {
3576 tANI_U8 *value = command;
3577 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3578 tANI_U8 numChannels = 0;
3579 eHalStatus status = eHAL_STATUS_SUCCESS;
3580
3581 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3582 if (eHAL_STATUS_SUCCESS != status)
3583 {
3584 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3585 "%s: Failed to parse channel list information", __func__);
3586 ret = -EINVAL;
3587 goto exit;
3588 }
3589
3590 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3591 {
3592 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3593 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3594 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3595 ret = -EINVAL;
3596 goto exit;
3597 }
3598 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3599 ChannelList,
3600 numChannels);
3601 if (eHAL_STATUS_SUCCESS != status)
3602 {
3603 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3604 "%s: Failed to update channel list information", __func__);
3605 ret = -EINVAL;
3606 goto exit;
3607 }
3608 }
3609 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3610 {
3611 tANI_U8 *value = command;
3612 char extra[128] = {0};
3613 int len = 0;
3614 tANI_U8 tid = 0;
3615 hdd_station_ctx_t *pHddStaCtx = NULL;
3616 tAniTrafStrmMetrics tsmMetrics;
3617 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3618
3619 /* if not associated, return error */
3620 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3621 {
3622 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3623 ret = -EINVAL;
3624 goto exit;
3625 }
3626
3627 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3628 value = value + 12;
3629 /* Convert the value from ascii to integer */
3630 ret = kstrtou8(value, 10, &tid);
3631 if (ret < 0)
3632 {
3633 /* If the input value is greater than max value of datatype, then also
3634 kstrtou8 fails */
3635 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3636 "%s: kstrtou8 failed range [%d - %d]", __func__,
3637 TID_MIN_VALUE,
3638 TID_MAX_VALUE);
3639 ret = -EINVAL;
3640 goto exit;
3641 }
3642
3643 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3644 {
3645 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3646 "tid value %d is out of range"
3647 " (Min: %d Max: %d)", tid,
3648 TID_MIN_VALUE,
3649 TID_MAX_VALUE);
3650 ret = -EINVAL;
3651 goto exit;
3652 }
3653
3654 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3655 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3656
3657 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3658 {
3659 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3660 "%s: failed to get tsm stats", __func__);
3661 ret = -EFAULT;
3662 goto exit;
3663 }
3664
3665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3666 "UplinkPktQueueDly(%d)\n"
3667 "UplinkPktQueueDlyHist[0](%d)\n"
3668 "UplinkPktQueueDlyHist[1](%d)\n"
3669 "UplinkPktQueueDlyHist[2](%d)\n"
3670 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303671 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003672 "UplinkPktLoss(%d)\n"
3673 "UplinkPktCount(%d)\n"
3674 "RoamingCount(%d)\n"
3675 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3676 tsmMetrics.UplinkPktQueueDlyHist[0],
3677 tsmMetrics.UplinkPktQueueDlyHist[1],
3678 tsmMetrics.UplinkPktQueueDlyHist[2],
3679 tsmMetrics.UplinkPktQueueDlyHist[3],
3680 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3681 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3682
3683 /* Output TSM stats is of the format
3684 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3685 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003686 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003687 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3688 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3689 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3690 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3691 tsmMetrics.RoamingDly);
3692
3693 if (copy_to_user(priv_data.buf, &extra, len + 1))
3694 {
3695 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3696 "%s: failed to copy data to user buffer", __func__);
3697 ret = -EFAULT;
3698 goto exit;
3699 }
3700 }
3701 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3702 {
3703 tANI_U8 *value = command;
3704 tANI_U8 *cckmIe = NULL;
3705 tANI_U8 cckmIeLen = 0;
3706 eHalStatus status = eHAL_STATUS_SUCCESS;
3707
3708 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3709 if (eHAL_STATUS_SUCCESS != status)
3710 {
3711 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3712 "%s: Failed to parse cckm ie data", __func__);
3713 ret = -EINVAL;
3714 goto exit;
3715 }
3716
3717 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3718 {
3719 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3720 "%s: CCKM Ie input length is more than max[%d]", __func__,
3721 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003722 vos_mem_free(cckmIe);
3723 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003724 ret = -EINVAL;
3725 goto exit;
3726 }
3727 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003728 vos_mem_free(cckmIe);
3729 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003730 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003731 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3732 {
3733 tANI_U8 *value = command;
3734 tCsrCcxBeaconReq ccxBcnReq;
3735 eHalStatus status = eHAL_STATUS_SUCCESS;
3736 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3737 if (eHAL_STATUS_SUCCESS != status)
3738 {
3739 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3740 "%s: Failed to parse ccx beacon req", __func__);
3741 ret = -EINVAL;
3742 goto exit;
3743 }
3744
3745 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3746 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003747#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003748 else {
3749 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3750 __func__, command);
3751 }
3752
Jeff Johnson295189b2012-06-20 16:38:30 -07003753 }
3754exit:
3755 if (command)
3756 {
3757 kfree(command);
3758 }
3759 return ret;
3760}
3761
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003762
3763
3764#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003765/**---------------------------------------------------------------------------
3766
3767 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3768
3769 This function parses the ccx beacon request passed in the format
3770 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3771 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3772 <space>Scan Mode N<space>Meas Duration N
3773 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3774 then take N.
3775 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3776 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3777 This function does not take care of removing duplicate channels from the list
3778
3779 \param - pValue Pointer to data
3780 \param - pCcxBcnReq output pointer to store parsed ie information
3781
3782 \return - 0 for success non-zero for failure
3783
3784 --------------------------------------------------------------------------*/
3785static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3786 tCsrCcxBeaconReq *pCcxBcnReq)
3787{
3788 tANI_U8 *inPtr = pValue;
3789 int tempInt = 0;
3790 int j = 0, i = 0, v = 0;
3791 char buf[32];
3792
3793 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3794 /*no argument after the command*/
3795 if (NULL == inPtr)
3796 {
3797 return -EINVAL;
3798 }
3799 /*no space after the command*/
3800 else if (SPACE_ASCII_VALUE != *inPtr)
3801 {
3802 return -EINVAL;
3803 }
3804
3805 /*removing empty spaces*/
3806 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3807
3808 /*no argument followed by spaces*/
3809 if ('\0' == *inPtr) return -EINVAL;
3810
3811 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003812 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003813 if (1 != v) return -EINVAL;
3814
3815 v = kstrtos32(buf, 10, &tempInt);
3816 if ( v < 0) return -EINVAL;
3817
3818 pCcxBcnReq->numBcnReqIe = tempInt;
3819
3820 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3821 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3822
3823 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3824 {
3825 for (i = 0; i < 4; i++)
3826 {
3827 /*inPtr pointing to the beginning of first space after number of ie fields*/
3828 inPtr = strpbrk( inPtr, " " );
3829 /*no ie data after the number of ie fields argument*/
3830 if (NULL == inPtr) return -EINVAL;
3831
3832 /*removing empty space*/
3833 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3834
3835 /*no ie data after the number of ie fields argument and spaces*/
3836 if ( '\0' == *inPtr ) return -EINVAL;
3837
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003838 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003839 if (1 != v) return -EINVAL;
3840
3841 v = kstrtos32(buf, 10, &tempInt);
3842 if (v < 0) return -EINVAL;
3843
3844 switch (i)
3845 {
3846 case 0: /* Measurement token */
3847 if (tempInt <= 0)
3848 {
3849 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3850 "Invalid Measurement Token(%d)", tempInt);
3851 return -EINVAL;
3852 }
3853 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3854 break;
3855
3856 case 1: /* Channel number */
3857 if ((tempInt <= 0) ||
3858 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3859 {
3860 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3861 "Invalid Channel Number(%d)", tempInt);
3862 return -EINVAL;
3863 }
3864 pCcxBcnReq->bcnReq[j].channel = tempInt;
3865 break;
3866
3867 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003868 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003869 {
3870 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3871 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3872 return -EINVAL;
3873 }
3874 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3875 break;
3876
3877 case 3: /* Measurement duration */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003878 if (((tempInt <= 0) && (pCcxBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
3879 ((tempInt < 0) && (pCcxBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003880 {
3881 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3882 "Invalid Measurement Duration(%d)", tempInt);
3883 return -EINVAL;
3884 }
3885 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3886 break;
3887 }
3888 }
3889 }
3890
3891 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3892 {
3893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303894 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003895 j,
3896 pCcxBcnReq->bcnReq[j].measurementToken,
3897 pCcxBcnReq->bcnReq[j].channel,
3898 pCcxBcnReq->bcnReq[j].scanMode,
3899 pCcxBcnReq->bcnReq[j].measurementDuration);
3900 }
3901
3902 return VOS_STATUS_SUCCESS;
3903}
3904
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003905static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3906{
3907 struct statsContext *pStatsContext = NULL;
3908 hdd_adapter_t *pAdapter = NULL;
3909
3910 if (NULL == pContext)
3911 {
3912 hddLog(VOS_TRACE_LEVEL_ERROR,
3913 "%s: Bad param, pContext [%p]",
3914 __func__, pContext);
3915 return;
3916 }
3917
Jeff Johnson72a40512013-12-19 10:14:15 -08003918 /* there is a race condition that exists between this callback
3919 function and the caller since the caller could time out either
3920 before or while this code is executing. we use a spinlock to
3921 serialize these actions */
3922 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003923
3924 pStatsContext = pContext;
3925 pAdapter = pStatsContext->pAdapter;
3926 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3927 {
3928 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08003929 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003930 hddLog(VOS_TRACE_LEVEL_WARN,
3931 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3932 __func__, pAdapter, pStatsContext->magic);
3933 return;
3934 }
3935
Jeff Johnson72a40512013-12-19 10:14:15 -08003936 /* context is valid so caller is still waiting */
3937
3938 /* paranoia: invalidate the magic */
3939 pStatsContext->magic = 0;
3940
3941 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003942 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3943 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3944 tsmMetrics.UplinkPktQueueDlyHist,
3945 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3946 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3947 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3948 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3949 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3950 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3951 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3952
Jeff Johnson72a40512013-12-19 10:14:15 -08003953 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003954 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08003955
3956 /* serialization is complete */
3957 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003958}
3959
3960
3961
3962static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3963 tAniTrafStrmMetrics* pTsmMetrics)
3964{
3965 hdd_station_ctx_t *pHddStaCtx = NULL;
3966 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08003967 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003968 long lrc;
3969 struct statsContext context;
3970 hdd_context_t *pHddCtx = NULL;
3971
3972 if (NULL == pAdapter)
3973 {
3974 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3975 return VOS_STATUS_E_FAULT;
3976 }
3977
3978 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3979 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3980
3981 /* we are connected prepare our callback context */
3982 init_completion(&context.completion);
3983 context.pAdapter = pAdapter;
3984 context.magic = STATS_CONTEXT_MAGIC;
3985
3986 /* query tsm stats */
3987 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
3988 pHddStaCtx->conn_info.staId[ 0 ],
3989 pHddStaCtx->conn_info.bssId,
3990 &context, pHddCtx->pvosContext, tid);
3991
3992 if (eHAL_STATUS_SUCCESS != hstatus)
3993 {
Jeff Johnson72a40512013-12-19 10:14:15 -08003994 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
3995 __func__);
3996 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003997 }
3998 else
3999 {
4000 /* request was sent -- wait for the response */
4001 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4002 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004003 if (lrc <= 0)
4004 {
4005 hddLog(VOS_TRACE_LEVEL_ERROR,
4006 "%s: SME %s while retrieving statistics",
4007 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004008 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004009 }
4010 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004011
Jeff Johnson72a40512013-12-19 10:14:15 -08004012 /* either we never sent a request, we sent a request and received a
4013 response or we sent a request and timed out. if we never sent a
4014 request or if we sent a request and got a response, we want to
4015 clear the magic out of paranoia. if we timed out there is a
4016 race condition such that the callback function could be
4017 executing at the same time we are. of primary concern is if the
4018 callback function had already verified the "magic" but had not
4019 yet set the completion variable when a timeout occurred. we
4020 serialize these activities by invalidating the magic while
4021 holding a shared spinlock which will cause us to block if the
4022 callback is currently executing */
4023 spin_lock(&hdd_context_lock);
4024 context.magic = 0;
4025 spin_unlock(&hdd_context_lock);
4026
4027 if (VOS_STATUS_SUCCESS == vstatus)
4028 {
4029 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4030 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4031 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4032 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4033 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4034 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4035 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4036 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4037 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4038 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4039 }
4040 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004041}
4042#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4043
Srinivas Girigowdade697412013-02-14 16:31:48 -08004044#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
4045void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4046{
4047 eCsrBand band = -1;
4048 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4049 switch (band)
4050 {
4051 case eCSR_BAND_ALL:
4052 *pBand = WLAN_HDD_UI_BAND_AUTO;
4053 break;
4054
4055 case eCSR_BAND_24:
4056 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4057 break;
4058
4059 case eCSR_BAND_5G:
4060 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4061 break;
4062
4063 default:
4064 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4065 *pBand = -1;
4066 break;
4067 }
4068}
4069
4070/**---------------------------------------------------------------------------
4071
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004072 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4073
4074 This function parses the send action frame data passed in the format
4075 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4076
Srinivas Girigowda56076852013-08-20 14:00:50 -07004077 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004078 \param - pTargetApBssid Pointer to target Ap bssid
4079 \param - pChannel Pointer to the Target AP channel
4080 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4081 \param - pBuf Pointer to data
4082 \param - pBufLen Pointer to data length
4083
4084 \return - 0 for success non-zero for failure
4085
4086 --------------------------------------------------------------------------*/
4087VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4088 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4089{
4090 tANI_U8 *inPtr = pValue;
4091 tANI_U8 *dataEnd;
4092 int tempInt;
4093 int j = 0;
4094 int i = 0;
4095 int v = 0;
4096 tANI_U8 tempBuf[32];
4097 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004098 /* 12 hexa decimal digits, 5 ':' and '\0' */
4099 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004100
4101 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4102 /*no argument after the command*/
4103 if (NULL == inPtr)
4104 {
4105 return -EINVAL;
4106 }
4107
4108 /*no space after the command*/
4109 else if (SPACE_ASCII_VALUE != *inPtr)
4110 {
4111 return -EINVAL;
4112 }
4113
4114 /*removing empty spaces*/
4115 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4116
4117 /*no argument followed by spaces*/
4118 if ('\0' == *inPtr)
4119 {
4120 return -EINVAL;
4121 }
4122
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004123 v = sscanf(inPtr, "%17s", macAddress);
4124 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004125 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004126 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4127 "Invalid MAC address or All hex inputs are not read (%d)", v);
4128 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004129 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004130
4131 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4132 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4133 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4134 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4135 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4136 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004137
4138 /* point to the next argument */
4139 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4140 /*no argument after the command*/
4141 if (NULL == inPtr) return -EINVAL;
4142
4143 /*removing empty spaces*/
4144 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4145
4146 /*no argument followed by spaces*/
4147 if ('\0' == *inPtr)
4148 {
4149 return -EINVAL;
4150 }
4151
4152 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004153 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004154 if (1 != v) return -EINVAL;
4155
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004156 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashishc0126762014-02-17 19:30:26 +05304157 if ( v < 0 || tempInt < 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304158 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004159
4160 *pChannel = tempInt;
4161
4162 /* point to the next argument */
4163 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4164 /*no argument after the command*/
4165 if (NULL == inPtr) return -EINVAL;
4166 /*removing empty spaces*/
4167 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4168
4169 /*no argument followed by spaces*/
4170 if ('\0' == *inPtr)
4171 {
4172 return -EINVAL;
4173 }
4174
4175 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004176 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004177 if (1 != v) return -EINVAL;
4178
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004179 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004180 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004181
4182 *pDwellTime = tempInt;
4183
4184 /* point to the next argument */
4185 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4186 /*no argument after the command*/
4187 if (NULL == inPtr) return -EINVAL;
4188 /*removing empty spaces*/
4189 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4190
4191 /*no argument followed by spaces*/
4192 if ('\0' == *inPtr)
4193 {
4194 return -EINVAL;
4195 }
4196
4197 /* find the length of data */
4198 dataEnd = inPtr;
4199 while(('\0' != *dataEnd) )
4200 {
4201 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004202 }
Kiet Lambe150c22013-11-21 16:30:32 +05304203 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004204 if ( *pBufLen <= 0) return -EINVAL;
4205
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004206 /* Allocate the number of bytes based on the number of input characters
4207 whether it is even or odd.
4208 if the number of input characters are even, then we need N/2 byte.
4209 if the number of input characters are odd, then we need do (N+1)/2 to
4210 compensate rounding off.
4211 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4212 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4213 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004214 if (NULL == *pBuf)
4215 {
4216 hddLog(VOS_TRACE_LEVEL_FATAL,
4217 "%s: vos_mem_alloc failed ", __func__);
4218 return -EINVAL;
4219 }
4220
4221 /* the buffer received from the upper layer is character buffer,
4222 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4223 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4224 and f0 in 3rd location */
4225 for (i = 0, j = 0; j < *pBufLen; j += 2)
4226 {
Kiet Lambe150c22013-11-21 16:30:32 +05304227 if( j+1 == *pBufLen)
4228 {
4229 tempByte = hdd_parse_hex(inPtr[j]);
4230 }
4231 else
4232 {
4233 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4234 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004235 (*pBuf)[i++] = tempByte;
4236 }
4237 *pBufLen = i;
4238 return VOS_STATUS_SUCCESS;
4239}
4240
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004241/**---------------------------------------------------------------------------
4242
Srinivas Girigowdade697412013-02-14 16:31:48 -08004243 \brief hdd_parse_channellist() - HDD Parse channel list
4244
4245 This function parses the channel list passed in the format
4246 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004247 if the Number of channels (N) does not match with the actual number of channels passed
4248 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4249 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4250 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4251 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004252
4253 \param - pValue Pointer to input channel list
4254 \param - ChannelList Pointer to local output array to record channel list
4255 \param - pNumChannels Pointer to number of roam scan channels
4256
4257 \return - 0 for success non-zero for failure
4258
4259 --------------------------------------------------------------------------*/
4260VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4261{
4262 tANI_U8 *inPtr = pValue;
4263 int tempInt;
4264 int j = 0;
4265 int v = 0;
4266 char buf[32];
4267
4268 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4269 /*no argument after the command*/
4270 if (NULL == inPtr)
4271 {
4272 return -EINVAL;
4273 }
4274
4275 /*no space after the command*/
4276 else if (SPACE_ASCII_VALUE != *inPtr)
4277 {
4278 return -EINVAL;
4279 }
4280
4281 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004282 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004283
4284 /*no argument followed by spaces*/
4285 if ('\0' == *inPtr)
4286 {
4287 return -EINVAL;
4288 }
4289
4290 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004291 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004292 if (1 != v) return -EINVAL;
4293
Srinivas Girigowdade697412013-02-14 16:31:48 -08004294 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004295 if ((v < 0) ||
4296 (tempInt <= 0) ||
4297 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4298 {
4299 return -EINVAL;
4300 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004301
4302 *pNumChannels = tempInt;
4303
4304 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4305 "Number of channels are: %d", *pNumChannels);
4306
4307 for (j = 0; j < (*pNumChannels); j++)
4308 {
4309 /*inPtr pointing to the beginning of first space after number of channels*/
4310 inPtr = strpbrk( inPtr, " " );
4311 /*no channel list after the number of channels argument*/
4312 if (NULL == inPtr)
4313 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004314 if (0 != j)
4315 {
4316 *pNumChannels = j;
4317 return VOS_STATUS_SUCCESS;
4318 }
4319 else
4320 {
4321 return -EINVAL;
4322 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004323 }
4324
4325 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004326 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004327
4328 /*no channel list after the number of channels argument and spaces*/
4329 if ( '\0' == *inPtr )
4330 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004331 if (0 != j)
4332 {
4333 *pNumChannels = j;
4334 return VOS_STATUS_SUCCESS;
4335 }
4336 else
4337 {
4338 return -EINVAL;
4339 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004340 }
4341
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004342 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004343 if (1 != v) return -EINVAL;
4344
Srinivas Girigowdade697412013-02-14 16:31:48 -08004345 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004346 if ((v < 0) ||
4347 (tempInt <= 0) ||
4348 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4349 {
4350 return -EINVAL;
4351 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004352 pChannelList[j] = tempInt;
4353
4354 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4355 "Channel %d added to preferred channel list",
4356 pChannelList[j] );
4357 }
4358
Srinivas Girigowdade697412013-02-14 16:31:48 -08004359 return VOS_STATUS_SUCCESS;
4360}
4361
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004362
4363/**---------------------------------------------------------------------------
4364
4365 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4366
4367 This function parses the reasoc command data passed in the format
4368 REASSOC<space><bssid><space><channel>
4369
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004370 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004371 \param - pTargetApBssid Pointer to target Ap bssid
4372 \param - pChannel Pointer to the Target AP channel
4373
4374 \return - 0 for success non-zero for failure
4375
4376 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004377VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4378 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004379{
4380 tANI_U8 *inPtr = pValue;
4381 int tempInt;
4382 int v = 0;
4383 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004384 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004385 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004386
4387 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4388 /*no argument after the command*/
4389 if (NULL == inPtr)
4390 {
4391 return -EINVAL;
4392 }
4393
4394 /*no space after the command*/
4395 else if (SPACE_ASCII_VALUE != *inPtr)
4396 {
4397 return -EINVAL;
4398 }
4399
4400 /*removing empty spaces*/
4401 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4402
4403 /*no argument followed by spaces*/
4404 if ('\0' == *inPtr)
4405 {
4406 return -EINVAL;
4407 }
4408
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004409 v = sscanf(inPtr, "%17s", macAddress);
4410 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004411 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004412 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4413 "Invalid MAC address or All hex inputs are not read (%d)", v);
4414 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004415 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004416
4417 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4418 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4419 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4420 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4421 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4422 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004423
4424 /* point to the next argument */
4425 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4426 /*no argument after the command*/
4427 if (NULL == inPtr) return -EINVAL;
4428
4429 /*removing empty spaces*/
4430 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4431
4432 /*no argument followed by spaces*/
4433 if ('\0' == *inPtr)
4434 {
4435 return -EINVAL;
4436 }
4437
4438 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004439 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004440 if (1 != v) return -EINVAL;
4441
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004442 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004443 if ((v < 0) ||
4444 (tempInt <= 0) ||
4445 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4446 {
4447 return -EINVAL;
4448 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004449
4450 *pChannel = tempInt;
4451 return VOS_STATUS_SUCCESS;
4452}
4453
4454#endif
4455
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004456#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4457/**---------------------------------------------------------------------------
4458
4459 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4460
4461 This function parses the SETCCKM IE command
4462 SETCCKMIE<space><ie data>
4463
4464 \param - pValue Pointer to input data
4465 \param - pCckmIe Pointer to output cckm Ie
4466 \param - pCckmIeLen Pointer to output cckm ie length
4467
4468 \return - 0 for success non-zero for failure
4469
4470 --------------------------------------------------------------------------*/
4471VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4472 tANI_U8 *pCckmIeLen)
4473{
4474 tANI_U8 *inPtr = pValue;
4475 tANI_U8 *dataEnd;
4476 int j = 0;
4477 int i = 0;
4478 tANI_U8 tempByte = 0;
4479
4480 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4481 /*no argument after the command*/
4482 if (NULL == inPtr)
4483 {
4484 return -EINVAL;
4485 }
4486
4487 /*no space after the command*/
4488 else if (SPACE_ASCII_VALUE != *inPtr)
4489 {
4490 return -EINVAL;
4491 }
4492
4493 /*removing empty spaces*/
4494 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4495
4496 /*no argument followed by spaces*/
4497 if ('\0' == *inPtr)
4498 {
4499 return -EINVAL;
4500 }
4501
4502 /* find the length of data */
4503 dataEnd = inPtr;
4504 while(('\0' != *dataEnd) )
4505 {
4506 dataEnd++;
4507 ++(*pCckmIeLen);
4508 }
4509 if ( *pCckmIeLen <= 0) return -EINVAL;
4510
4511 /* Allocate the number of bytes based on the number of input characters
4512 whether it is even or odd.
4513 if the number of input characters are even, then we need N/2 byte.
4514 if the number of input characters are odd, then we need do (N+1)/2 to
4515 compensate rounding off.
4516 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4517 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4518 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4519 if (NULL == *pCckmIe)
4520 {
4521 hddLog(VOS_TRACE_LEVEL_FATAL,
4522 "%s: vos_mem_alloc failed ", __func__);
4523 return -EINVAL;
4524 }
4525 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4526 /* the buffer received from the upper layer is character buffer,
4527 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4528 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4529 and f0 in 3rd location */
4530 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4531 {
4532 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4533 (*pCckmIe)[i++] = tempByte;
4534 }
4535 *pCckmIeLen = i;
4536
4537 return VOS_STATUS_SUCCESS;
4538}
4539#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4540
Jeff Johnson295189b2012-06-20 16:38:30 -07004541/**---------------------------------------------------------------------------
4542
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004543 \brief hdd_is_valid_mac_address() - Validate MAC address
4544
4545 This function validates whether the given MAC address is valid or not
4546 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4547 where X is the hexa decimal digit character and separated by ':'
4548 This algorithm works even if MAC address is not separated by ':'
4549
4550 This code checks given input string mac contains exactly 12 hexadecimal digits.
4551 and a separator colon : appears in the input string only after
4552 an even number of hex digits.
4553
4554 \param - pMacAddr pointer to the input MAC address
4555 \return - 1 for valid and 0 for invalid
4556
4557 --------------------------------------------------------------------------*/
4558
4559v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4560{
4561 int xdigit = 0;
4562 int separator = 0;
4563 while (*pMacAddr)
4564 {
4565 if (isxdigit(*pMacAddr))
4566 {
4567 xdigit++;
4568 }
4569 else if (':' == *pMacAddr)
4570 {
4571 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4572 break;
4573
4574 ++separator;
4575 }
4576 else
4577 {
4578 separator = -1;
4579 /* Invalid MAC found */
4580 return 0;
4581 }
4582 ++pMacAddr;
4583 }
4584 return (xdigit == 12 && (separator == 5 || separator == 0));
4585}
4586
4587/**---------------------------------------------------------------------------
4588
Jeff Johnson295189b2012-06-20 16:38:30 -07004589 \brief hdd_open() - HDD Open function
4590
4591 This is called in response to ifconfig up
4592
4593 \param - dev Pointer to net_device structure
4594
4595 \return - 0 for success non-zero for failure
4596
4597 --------------------------------------------------------------------------*/
4598int hdd_open (struct net_device *dev)
4599{
4600 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4601 hdd_context_t *pHddCtx;
4602 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4603 VOS_STATUS status;
4604 v_BOOL_t in_standby = TRUE;
4605
4606 if (NULL == pAdapter)
4607 {
4608 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304609 "%s: pAdapter 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
4621 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4622 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4623 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004624 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4625 {
4626 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304627 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004628 in_standby = FALSE;
4629 break;
4630 }
4631 else
4632 {
4633 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4634 pAdapterNode = pNext;
4635 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004636 }
4637
4638 if (TRUE == in_standby)
4639 {
4640 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4641 {
4642 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4643 "wlan out of power save", __func__);
4644 return -EINVAL;
4645 }
4646 }
4647
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004648 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004649 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4650 {
4651 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004652 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004653 /* Enable TX queues only when we are connected */
4654 netif_tx_start_all_queues(dev);
4655 }
4656
4657 return 0;
4658}
4659
4660int hdd_mon_open (struct net_device *dev)
4661{
4662 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4663
4664 if(pAdapter == NULL) {
4665 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004666 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004667 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004668 }
4669
4670 netif_start_queue(dev);
4671
4672 return 0;
4673}
4674/**---------------------------------------------------------------------------
4675
4676 \brief hdd_stop() - HDD stop function
4677
4678 This is called in response to ifconfig down
4679
4680 \param - dev Pointer to net_device structure
4681
4682 \return - 0 for success non-zero for failure
4683
4684 --------------------------------------------------------------------------*/
4685
4686int hdd_stop (struct net_device *dev)
4687{
4688 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4689 hdd_context_t *pHddCtx;
4690 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4691 VOS_STATUS status;
4692 v_BOOL_t enter_standby = TRUE;
4693
4694 ENTER();
4695
4696 if (NULL == pAdapter)
4697 {
4698 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304699 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004700 return -ENODEV;
4701 }
4702
4703 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4704 if (NULL == pHddCtx)
4705 {
4706 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004707 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004708 return -ENODEV;
4709 }
4710
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004711 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004712 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4713 netif_tx_disable(pAdapter->dev);
4714 netif_carrier_off(pAdapter->dev);
4715
4716
4717 /* SoftAP ifaces should never go in power save mode
4718 making sure same here. */
4719 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4720 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004721 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004722 )
4723 {
4724 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304725 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4726 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004727 EXIT();
4728 return 0;
4729 }
4730
4731 /* Find if any iface is up then
4732 if any iface is up then can't put device to sleep/ power save mode. */
4733 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4734 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4735 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004736 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4737 {
4738 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304739 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004740 enter_standby = FALSE;
4741 break;
4742 }
4743 else
4744 {
4745 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4746 pAdapterNode = pNext;
4747 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004748 }
4749
4750 if (TRUE == enter_standby)
4751 {
4752 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4753 "entering standby", __func__);
4754 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4755 {
4756 /*log and return success*/
4757 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4758 "wlan in power save", __func__);
4759 }
4760 }
4761
4762 EXIT();
4763 return 0;
4764}
4765
4766/**---------------------------------------------------------------------------
4767
4768 \brief hdd_uninit() - HDD uninit function
4769
4770 This is called during the netdev unregister to uninitialize all data
4771associated with the device
4772
4773 \param - dev Pointer to net_device structure
4774
4775 \return - void
4776
4777 --------------------------------------------------------------------------*/
4778static void hdd_uninit (struct net_device *dev)
4779{
4780 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4781
4782 ENTER();
4783
4784 do
4785 {
4786 if (NULL == pAdapter)
4787 {
4788 hddLog(VOS_TRACE_LEVEL_FATAL,
4789 "%s: NULL pAdapter", __func__);
4790 break;
4791 }
4792
4793 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4794 {
4795 hddLog(VOS_TRACE_LEVEL_FATAL,
4796 "%s: Invalid magic", __func__);
4797 break;
4798 }
4799
4800 if (NULL == pAdapter->pHddCtx)
4801 {
4802 hddLog(VOS_TRACE_LEVEL_FATAL,
4803 "%s: NULL pHddCtx", __func__);
4804 break;
4805 }
4806
4807 if (dev != pAdapter->dev)
4808 {
4809 hddLog(VOS_TRACE_LEVEL_FATAL,
4810 "%s: Invalid device reference", __func__);
4811 /* we haven't validated all cases so let this go for now */
4812 }
4813
4814 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4815
4816 /* after uninit our adapter structure will no longer be valid */
4817 pAdapter->dev = NULL;
4818 pAdapter->magic = 0;
4819 } while (0);
4820
4821 EXIT();
4822}
4823
4824/**---------------------------------------------------------------------------
4825
4826 \brief hdd_release_firmware() -
4827
4828 This function calls the release firmware API to free the firmware buffer.
4829
4830 \param - pFileName Pointer to the File Name.
4831 pCtx - Pointer to the adapter .
4832
4833
4834 \return - 0 for success, non zero for failure
4835
4836 --------------------------------------------------------------------------*/
4837
4838VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4839{
4840 VOS_STATUS status = VOS_STATUS_SUCCESS;
4841 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4842 ENTER();
4843
4844
4845 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4846
4847 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4848
4849 if(pHddCtx->fw) {
4850 release_firmware(pHddCtx->fw);
4851 pHddCtx->fw = NULL;
4852 }
4853 else
4854 status = VOS_STATUS_E_FAILURE;
4855 }
4856 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4857 if(pHddCtx->nv) {
4858 release_firmware(pHddCtx->nv);
4859 pHddCtx->nv = NULL;
4860 }
4861 else
4862 status = VOS_STATUS_E_FAILURE;
4863
4864 }
4865
4866 EXIT();
4867 return status;
4868}
4869
4870/**---------------------------------------------------------------------------
4871
4872 \brief hdd_request_firmware() -
4873
4874 This function reads the firmware file using the request firmware
4875 API and returns the the firmware data and the firmware file size.
4876
4877 \param - pfileName - Pointer to the file name.
4878 - pCtx - Pointer to the adapter .
4879 - ppfw_data - Pointer to the pointer of the firmware data.
4880 - pSize - Pointer to the file size.
4881
4882 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4883
4884 --------------------------------------------------------------------------*/
4885
4886
4887VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4888{
4889 int status;
4890 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4891 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4892 ENTER();
4893
4894 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4895
4896 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4897
4898 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4899 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4900 __func__, pfileName);
4901 retval = VOS_STATUS_E_FAILURE;
4902 }
4903
4904 else {
4905 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4906 *pSize = pHddCtx->fw->size;
4907 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4908 __func__, *pSize);
4909 }
4910 }
4911 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4912
4913 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4914
4915 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4916 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4917 __func__, pfileName);
4918 retval = VOS_STATUS_E_FAILURE;
4919 }
4920
4921 else {
4922 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4923 *pSize = pHddCtx->nv->size;
4924 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4925 __func__, *pSize);
4926 }
4927 }
4928
4929 EXIT();
4930 return retval;
4931}
4932/**---------------------------------------------------------------------------
4933 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4934
4935 This is the function invoked by SME to inform the result of a full power
4936 request issued by HDD
4937
4938 \param - callbackcontext - Pointer to cookie
4939 status - result of request
4940
4941 \return - None
4942
4943--------------------------------------------------------------------------*/
4944void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4945{
4946 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4947
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004948 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004949 if(&pHddCtx->full_pwr_comp_var)
4950 {
4951 complete(&pHddCtx->full_pwr_comp_var);
4952 }
4953}
4954
4955/**---------------------------------------------------------------------------
4956
4957 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4958
4959 This is the function invoked by SME to inform the result of BMPS
4960 request issued by HDD
4961
4962 \param - callbackcontext - Pointer to cookie
4963 status - result of request
4964
4965 \return - None
4966
4967--------------------------------------------------------------------------*/
4968void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4969{
4970
4971 struct completion *completion_var = (struct completion*) callbackContext;
4972
Arif Hussain6d2a3322013-11-17 19:50:10 -08004973 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004974 if(completion_var != NULL)
4975 {
4976 complete(completion_var);
4977 }
4978}
4979
4980/**---------------------------------------------------------------------------
4981
4982 \brief hdd_get_cfg_file_size() -
4983
4984 This function reads the configuration file using the request firmware
4985 API and returns the configuration file size.
4986
4987 \param - pCtx - Pointer to the adapter .
4988 - pFileName - Pointer to the file name.
4989 - pBufSize - Pointer to the buffer size.
4990
4991 \return - 0 for success, non zero for failure
4992
4993 --------------------------------------------------------------------------*/
4994
4995VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
4996{
4997 int status;
4998 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4999
5000 ENTER();
5001
5002 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5003
5004 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5005 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5006 status = VOS_STATUS_E_FAILURE;
5007 }
5008 else {
5009 *pBufSize = pHddCtx->fw->size;
5010 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5011 release_firmware(pHddCtx->fw);
5012 pHddCtx->fw = NULL;
5013 }
5014
5015 EXIT();
5016 return VOS_STATUS_SUCCESS;
5017}
5018
5019/**---------------------------------------------------------------------------
5020
5021 \brief hdd_read_cfg_file() -
5022
5023 This function reads the configuration file using the request firmware
5024 API and returns the cfg data and the buffer size of the configuration file.
5025
5026 \param - pCtx - Pointer to the adapter .
5027 - pFileName - Pointer to the file name.
5028 - pBuffer - Pointer to the data buffer.
5029 - pBufSize - Pointer to the buffer size.
5030
5031 \return - 0 for success, non zero for failure
5032
5033 --------------------------------------------------------------------------*/
5034
5035VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5036 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5037{
5038 int status;
5039 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5040
5041 ENTER();
5042
5043 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5044
5045 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5046 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5047 return VOS_STATUS_E_FAILURE;
5048 }
5049 else {
5050 if(*pBufSize != pHddCtx->fw->size) {
5051 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5052 "file size", __func__);
5053 release_firmware(pHddCtx->fw);
5054 pHddCtx->fw = NULL;
5055 return VOS_STATUS_E_FAILURE;
5056 }
5057 else {
5058 if(pBuffer) {
5059 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5060 }
5061 release_firmware(pHddCtx->fw);
5062 pHddCtx->fw = NULL;
5063 }
5064 }
5065
5066 EXIT();
5067
5068 return VOS_STATUS_SUCCESS;
5069}
5070
5071/**---------------------------------------------------------------------------
5072
Jeff Johnson295189b2012-06-20 16:38:30 -07005073 \brief hdd_set_mac_address() -
5074
5075 This function sets the user specified mac address using
5076 the command ifconfig wlanX hw ether <mac adress>.
5077
5078 \param - dev - Pointer to the net device.
5079 - addr - Pointer to the sockaddr.
5080 \return - 0 for success, non zero for failure
5081
5082 --------------------------------------------------------------------------*/
5083
5084static int hdd_set_mac_address(struct net_device *dev, void *addr)
5085{
5086 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5087 struct sockaddr *psta_mac_addr = addr;
5088 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5089
5090 ENTER();
5091
5092 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5093
5094#ifdef HDD_SESSIONIZE
5095 // set the MAC address though the STA ID CFG.
5096 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5097 (v_U8_t *)&pAdapter->macAddressCurrent,
5098 sizeof( pAdapter->macAddressCurrent ),
5099 hdd_set_mac_addr_cb, VOS_FALSE );
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305100
5101 if(eHAL_STATUS_SUCCESS != halStatus)
5102 {
5103 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5104 "%s: failed to set MAC address in CFG", __func__);
5105 }
5106
Jeff Johnson295189b2012-06-20 16:38:30 -07005107#endif
5108
5109 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5110
5111 EXIT();
5112 return halStatus;
5113}
5114
5115tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5116{
5117 int i;
5118 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5119 {
Abhishek Singheb183782014-02-06 13:37:21 +05305120 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005121 break;
5122 }
5123
5124 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5125 return NULL;
5126
5127 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5128 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5129}
5130
5131void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5132{
5133 int i;
5134 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5135 {
5136 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5137 {
5138 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5139 break;
5140 }
5141 }
5142 return;
5143}
5144
5145#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5146 static struct net_device_ops wlan_drv_ops = {
5147 .ndo_open = hdd_open,
5148 .ndo_stop = hdd_stop,
5149 .ndo_uninit = hdd_uninit,
5150 .ndo_start_xmit = hdd_hard_start_xmit,
5151 .ndo_tx_timeout = hdd_tx_timeout,
5152 .ndo_get_stats = hdd_stats,
5153 .ndo_do_ioctl = hdd_ioctl,
5154 .ndo_set_mac_address = hdd_set_mac_address,
5155 .ndo_select_queue = hdd_select_queue,
5156#ifdef WLAN_FEATURE_PACKET_FILTERING
5157#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5158 .ndo_set_rx_mode = hdd_set_multicast_list,
5159#else
5160 .ndo_set_multicast_list = hdd_set_multicast_list,
5161#endif //LINUX_VERSION_CODE
5162#endif
5163 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005164 static struct net_device_ops wlan_mon_drv_ops = {
5165 .ndo_open = hdd_mon_open,
5166 .ndo_stop = hdd_stop,
5167 .ndo_uninit = hdd_uninit,
5168 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5169 .ndo_tx_timeout = hdd_tx_timeout,
5170 .ndo_get_stats = hdd_stats,
5171 .ndo_do_ioctl = hdd_ioctl,
5172 .ndo_set_mac_address = hdd_set_mac_address,
5173 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005174
5175#endif
5176
5177void hdd_set_station_ops( struct net_device *pWlanDev )
5178{
5179#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005180 pWlanDev->netdev_ops = &wlan_drv_ops;
5181#else
5182 pWlanDev->open = hdd_open;
5183 pWlanDev->stop = hdd_stop;
5184 pWlanDev->uninit = hdd_uninit;
5185 pWlanDev->hard_start_xmit = NULL;
5186 pWlanDev->tx_timeout = hdd_tx_timeout;
5187 pWlanDev->get_stats = hdd_stats;
5188 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005189 pWlanDev->set_mac_address = hdd_set_mac_address;
5190#endif
5191}
5192
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005193static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005194{
5195 struct net_device *pWlanDev = NULL;
5196 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005197 /*
5198 * cfg80211 initialization and registration....
5199 */
5200 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5201
Jeff Johnson295189b2012-06-20 16:38:30 -07005202 if(pWlanDev != NULL)
5203 {
5204
5205 //Save the pointer to the net_device in the HDD adapter
5206 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5207
Jeff Johnson295189b2012-06-20 16:38:30 -07005208 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5209
5210 pAdapter->dev = pWlanDev;
5211 pAdapter->pHddCtx = pHddCtx;
5212 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5213
5214 init_completion(&pAdapter->session_open_comp_var);
5215 init_completion(&pAdapter->session_close_comp_var);
5216 init_completion(&pAdapter->disconnect_comp_var);
5217 init_completion(&pAdapter->linkup_event_var);
5218 init_completion(&pAdapter->cancel_rem_on_chan_var);
5219 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005220#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5221 init_completion(&pAdapter->offchannel_tx_event);
5222#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005223 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005224#ifdef FEATURE_WLAN_TDLS
5225 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005226 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005227 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305228 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005229#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005230 init_completion(&pHddCtx->mc_sus_event_var);
5231 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305232 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005233 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005234 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005235
Rajeev79dbe4c2013-10-05 11:03:42 +05305236#ifdef FEATURE_WLAN_BATCH_SCAN
5237 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5238 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5239 pAdapter->pBatchScanRsp = NULL;
5240 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005241 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005242 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305243 mutex_init(&pAdapter->hdd_batch_scan_lock);
5244#endif
5245
Jeff Johnson295189b2012-06-20 16:38:30 -07005246 pAdapter->isLinkUpSvcNeeded = FALSE;
5247 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5248 //Init the net_device structure
5249 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5250
5251 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5252 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5253 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5254 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5255
5256 hdd_set_station_ops( pAdapter->dev );
5257
5258 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005259 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5260 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5261 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005262 /* set pWlanDev's parent to underlying device */
5263 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5264 }
5265
5266 return pAdapter;
5267}
5268
5269VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5270{
5271 struct net_device *pWlanDev = pAdapter->dev;
5272 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5273 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5274 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5275
5276 if( rtnl_lock_held )
5277 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005278 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005279 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5280 {
5281 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5282 return VOS_STATUS_E_FAILURE;
5283 }
5284 }
5285 if (register_netdevice(pWlanDev))
5286 {
5287 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5288 return VOS_STATUS_E_FAILURE;
5289 }
5290 }
5291 else
5292 {
5293 if(register_netdev(pWlanDev))
5294 {
5295 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5296 return VOS_STATUS_E_FAILURE;
5297 }
5298 }
5299 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5300
5301 return VOS_STATUS_SUCCESS;
5302}
5303
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005304static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005305{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005306 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005307
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005308 if (NULL == pAdapter)
5309 {
5310 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5311 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005312 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005313
5314 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5315 {
5316 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5317 return eHAL_STATUS_NOT_INITIALIZED;
5318 }
5319
5320 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5321
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005322#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005323 /* need to make sure all of our scheduled work has completed.
5324 * This callback is called from MC thread context, so it is safe to
5325 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005326 *
5327 * Even though this is called from MC thread context, if there is a faulty
5328 * work item in the system, that can hang this call forever. So flushing
5329 * this global work queue is not safe; and now we make sure that
5330 * individual work queues are stopped correctly. But the cancel work queue
5331 * is a GPL only API, so the proprietary version of the driver would still
5332 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005333 */
5334 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005335#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005336
5337 /* We can be blocked while waiting for scheduled work to be
5338 * flushed, and the adapter structure can potentially be freed, in
5339 * which case the magic will have been reset. So make sure the
5340 * magic is still good, and hence the adapter structure is still
5341 * valid, before signaling completion */
5342 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5343 {
5344 complete(&pAdapter->session_close_comp_var);
5345 }
5346
Jeff Johnson295189b2012-06-20 16:38:30 -07005347 return eHAL_STATUS_SUCCESS;
5348}
5349
5350VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5351{
5352 struct net_device *pWlanDev = pAdapter->dev;
5353 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5354 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5355 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5356 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305357 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005358
5359 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005360 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005361 //Open a SME session for future operation
5362 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005363 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005364 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5365 {
5366 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005367 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005368 halStatus, halStatus );
5369 status = VOS_STATUS_E_FAILURE;
5370 goto error_sme_open;
5371 }
5372
5373 //Block on a completion variable. Can't wait forever though.
5374 rc = wait_for_completion_interruptible_timeout(
5375 &pAdapter->session_open_comp_var,
5376 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305377 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005378 {
5379 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305380 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005381 status = VOS_STATUS_E_FAILURE;
5382 goto error_sme_open;
5383 }
5384
5385 // Register wireless extensions
5386 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5387 {
5388 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005389 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005390 halStatus, halStatus );
5391 status = VOS_STATUS_E_FAILURE;
5392 goto error_register_wext;
5393 }
5394 //Safe to register the hard_start_xmit function again
5395#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5396 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5397#else
5398 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5399#endif
5400
5401 //Set the Connection State to Not Connected
5402 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5403
5404 //Set the default operation channel
5405 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5406
5407 /* Make the default Auth Type as OPEN*/
5408 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5409
5410 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5411 {
5412 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005413 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005414 status, status );
5415 goto error_init_txrx;
5416 }
5417
5418 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5419
5420 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5421 {
5422 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005423 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005424 status, status );
5425 goto error_wmm_init;
5426 }
5427
5428 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5429
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005430#ifdef FEATURE_WLAN_TDLS
5431 if(0 != wlan_hdd_tdls_init(pAdapter))
5432 {
5433 status = VOS_STATUS_E_FAILURE;
5434 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5435 goto error_tdls_init;
5436 }
5437 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5438#endif
5439
Jeff Johnson295189b2012-06-20 16:38:30 -07005440 return VOS_STATUS_SUCCESS;
5441
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005442#ifdef FEATURE_WLAN_TDLS
5443error_tdls_init:
5444 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5445 hdd_wmm_adapter_close(pAdapter);
5446#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005447error_wmm_init:
5448 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5449 hdd_deinit_tx_rx(pAdapter);
5450error_init_txrx:
5451 hdd_UnregisterWext(pWlanDev);
5452error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005453 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005454 {
5455 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005456 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005457 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005458 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005459 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305460 unsigned long rc;
5461
Jeff Johnson295189b2012-06-20 16:38:30 -07005462 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305463 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005464 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005465 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305466 if (rc <= 0)
5467 hddLog(VOS_TRACE_LEVEL_ERROR,
5468 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005469 }
5470}
5471error_sme_open:
5472 return status;
5473}
5474
Jeff Johnson295189b2012-06-20 16:38:30 -07005475void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5476{
5477 hdd_cfg80211_state_t *cfgState;
5478
5479 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5480
5481 if( NULL != cfgState->buf )
5482 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305483 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07005484 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5485 rc = wait_for_completion_interruptible_timeout(
5486 &pAdapter->tx_action_cnf_event,
5487 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305488 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005489 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005490 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305491 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
5492 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005493 }
5494 }
5495 return;
5496}
Jeff Johnson295189b2012-06-20 16:38:30 -07005497
5498void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5499{
5500 ENTER();
5501 switch ( pAdapter->device_mode )
5502 {
5503 case WLAN_HDD_INFRA_STATION:
5504 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005505 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005506 {
5507 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5508 {
5509 hdd_deinit_tx_rx( pAdapter );
5510 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5511 }
5512
5513 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5514 {
5515 hdd_wmm_adapter_close( pAdapter );
5516 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5517 }
5518
Jeff Johnson295189b2012-06-20 16:38:30 -07005519 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005520#ifdef FEATURE_WLAN_TDLS
5521 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5522 {
5523 wlan_hdd_tdls_exit(pAdapter);
5524 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5525 }
5526#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005527
5528 break;
5529 }
5530
5531 case WLAN_HDD_SOFTAP:
5532 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005533 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305534
5535 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5536 {
5537 hdd_wmm_adapter_close( pAdapter );
5538 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5539 }
5540
Jeff Johnson295189b2012-06-20 16:38:30 -07005541 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005542
5543 hdd_unregister_hostapd(pAdapter);
5544 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005545 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005546 break;
5547 }
5548
5549 case WLAN_HDD_MONITOR:
5550 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005551 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005552 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5553 {
5554 hdd_deinit_tx_rx( pAdapter );
5555 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5556 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005557 if(NULL != pAdapterforTx)
5558 {
5559 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5560 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005561 break;
5562 }
5563
5564
5565 default:
5566 break;
5567 }
5568
5569 EXIT();
5570}
5571
5572void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5573{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08005574 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305575
5576 ENTER();
5577 if (NULL == pAdapter)
5578 {
5579 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5580 "%s: HDD adapter is Null", __func__);
5581 return;
5582 }
5583
5584 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005585
Rajeev79dbe4c2013-10-05 11:03:42 +05305586#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305587 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
5588 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08005589 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305590 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
5591 )
5592 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005593 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05305594 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005595 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
5596 {
5597 hdd_deinit_batch_scan(pAdapter);
5598 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305599 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08005600 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305601#endif
5602
Jeff Johnson295189b2012-06-20 16:38:30 -07005603 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5604 if( rtnl_held )
5605 {
5606 unregister_netdevice(pWlanDev);
5607 }
5608 else
5609 {
5610 unregister_netdev(pWlanDev);
5611 }
5612 // note that the pAdapter is no longer valid at this point
5613 // since the memory has been reclaimed
5614 }
5615
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305616 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005617}
5618
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005619void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5620{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305621 VOS_STATUS status;
5622 hdd_adapter_t *pAdapter = NULL;
5623 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005624
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305625 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005626
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305627 /*loop through all adapters.*/
5628 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005629 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305630 pAdapter = pAdapterNode->pAdapter;
5631 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5632 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005633
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305634 { // we skip this registration for modes other than STA and P2P client modes.
5635 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5636 pAdapterNode = pNext;
5637 continue;
5638 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005639
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305640 //Apply Dynamic DTIM For P2P
5641 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5642 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5643 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5644 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5645 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5646 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5647 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5648 (eConnectionState_Associated ==
5649 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5650 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5651 {
5652 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005653
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305654 powerRequest.uIgnoreDTIM = 1;
5655 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5656
5657 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5658 {
5659 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5660 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5661 }
5662 else
5663 {
5664 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5665 }
5666
5667 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5668 * specified during Enter/Exit BMPS when LCD off*/
5669 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5670 NULL, eANI_BOOLEAN_FALSE);
5671 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5672 NULL, eANI_BOOLEAN_FALSE);
5673
5674 /* switch to the DTIM specified in cfg.ini */
5675 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5676 "Switch to DTIM %d", powerRequest.uListenInterval);
5677 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5678 break;
5679
5680 }
5681
5682 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5683 pAdapterNode = pNext;
5684 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005685}
5686
5687void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5688{
5689 /*Switch back to DTIM 1*/
5690 tSirSetPowerParamsReq powerRequest = { 0 };
5691
5692 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5693 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005694 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005695
5696 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5697 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5698 NULL, eANI_BOOLEAN_FALSE);
5699 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5700 NULL, eANI_BOOLEAN_FALSE);
5701
5702 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5703 "Switch to DTIM%d",powerRequest.uListenInterval);
5704 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5705
5706}
5707
Jeff Johnson295189b2012-06-20 16:38:30 -07005708VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5709{
5710 VOS_STATUS status = VOS_STATUS_SUCCESS;
5711
5712 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5713 {
5714 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5715 }
5716
5717 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5718 {
5719 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5720 }
5721
5722 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5723 {
5724 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5725 }
5726
5727 return status;
5728}
5729
5730VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5731{
5732 hdd_adapter_t *pAdapter = NULL;
5733 eHalStatus halStatus;
5734 VOS_STATUS status = VOS_STATUS_E_INVAL;
5735 v_BOOL_t disableBmps = FALSE;
5736 v_BOOL_t disableImps = FALSE;
5737
5738 switch(session_type)
5739 {
5740 case WLAN_HDD_INFRA_STATION:
5741 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005742 case WLAN_HDD_P2P_CLIENT:
5743 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005744 //Exit BMPS -> Is Sta/P2P Client is already connected
5745 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5746 if((NULL != pAdapter)&&
5747 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5748 {
5749 disableBmps = TRUE;
5750 }
5751
5752 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5753 if((NULL != pAdapter)&&
5754 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5755 {
5756 disableBmps = TRUE;
5757 }
5758
5759 //Exit both Bmps and Imps incase of Go/SAP Mode
5760 if((WLAN_HDD_SOFTAP == session_type) ||
5761 (WLAN_HDD_P2P_GO == session_type))
5762 {
5763 disableBmps = TRUE;
5764 disableImps = TRUE;
5765 }
5766
5767 if(TRUE == disableImps)
5768 {
5769 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5770 {
5771 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5772 }
5773 }
5774
5775 if(TRUE == disableBmps)
5776 {
5777 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5778 {
5779 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5780
5781 if(eHAL_STATUS_SUCCESS != halStatus)
5782 {
5783 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005784 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005785 VOS_ASSERT(0);
5786 return status;
5787 }
5788 }
5789
5790 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5791 {
5792 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5793
5794 if(eHAL_STATUS_SUCCESS != halStatus)
5795 {
5796 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005797 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005798 VOS_ASSERT(0);
5799 return status;
5800 }
5801 }
5802 }
5803
5804 if((TRUE == disableBmps) ||
5805 (TRUE == disableImps))
5806 {
5807 /* Now, get the chip into Full Power now */
5808 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5809 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5810 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5811
5812 if(halStatus != eHAL_STATUS_SUCCESS)
5813 {
5814 if(halStatus == eHAL_STATUS_PMC_PENDING)
5815 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305816 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005817 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305818 ret = wait_for_completion_interruptible_timeout(
5819 &pHddCtx->full_pwr_comp_var,
5820 msecs_to_jiffies(1000));
5821 if (ret <= 0)
5822 {
5823 hddLog(VOS_TRACE_LEVEL_ERROR,
5824 "%s: wait on full_pwr_comp_var failed %ld",
5825 __func__, ret);
5826 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005827 }
5828 else
5829 {
5830 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005831 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005832 VOS_ASSERT(0);
5833 return status;
5834 }
5835 }
5836
5837 status = VOS_STATUS_SUCCESS;
5838 }
5839
5840 break;
5841 }
5842 return status;
5843}
5844
5845hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005846 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005847 tANI_U8 rtnl_held )
5848{
5849 hdd_adapter_t *pAdapter = NULL;
5850 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5851 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5852 VOS_STATUS exitbmpsStatus;
5853
Arif Hussain6d2a3322013-11-17 19:50:10 -08005854 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005855
5856 //Disable BMPS incase of Concurrency
5857 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5858
5859 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5860 {
5861 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305862 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005863 VOS_ASSERT(0);
5864 return NULL;
5865 }
5866
5867 switch(session_type)
5868 {
5869 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005870 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005871 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005872 {
5873 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5874
5875 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305876 {
5877 hddLog(VOS_TRACE_LEVEL_FATAL,
5878 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005879 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305880 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005881
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305882#ifdef FEATURE_WLAN_TDLS
5883 /* A Mutex Lock is introduced while changing/initializing the mode to
5884 * protect the concurrent access for the Adapters by TDLS module.
5885 */
5886 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5887 {
5888 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5889 "%s: unable to lock list", __func__);
5890 return NULL;
5891 }
5892#endif
5893
Jeff Johnsone7245742012-09-05 17:12:55 -07005894 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5895 NL80211_IFTYPE_P2P_CLIENT:
5896 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005897
Jeff Johnson295189b2012-06-20 16:38:30 -07005898 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305899#ifdef FEATURE_WLAN_TDLS
5900 mutex_unlock(&pHddCtx->tdls_lock);
5901#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05305902
5903 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005904 if( VOS_STATUS_SUCCESS != status )
5905 goto err_free_netdev;
5906
5907 status = hdd_register_interface( pAdapter, rtnl_held );
5908 if( VOS_STATUS_SUCCESS != status )
5909 {
5910 hdd_deinit_adapter(pHddCtx, pAdapter);
5911 goto err_free_netdev;
5912 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305913
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05305914 // Workqueue which gets scheduled in IPv4 notification callback.
5915 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
5916
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305917#ifdef WLAN_NS_OFFLOAD
5918 // Workqueue which gets scheduled in IPv6 notification callback.
5919 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5920#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005921 //Stop the Interface TX queue.
5922 netif_tx_disable(pAdapter->dev);
5923 //netif_tx_disable(pWlanDev);
5924 netif_carrier_off(pAdapter->dev);
5925
5926 break;
5927 }
5928
Jeff Johnson295189b2012-06-20 16:38:30 -07005929 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005930 case WLAN_HDD_SOFTAP:
5931 {
5932 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5933 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305934 {
5935 hddLog(VOS_TRACE_LEVEL_FATAL,
5936 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005937 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305938 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005939
Jeff Johnson295189b2012-06-20 16:38:30 -07005940 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5941 NL80211_IFTYPE_AP:
5942 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005943 pAdapter->device_mode = session_type;
5944
5945 status = hdd_init_ap_mode(pAdapter);
5946 if( VOS_STATUS_SUCCESS != status )
5947 goto err_free_netdev;
5948
5949 status = hdd_register_hostapd( pAdapter, rtnl_held );
5950 if( VOS_STATUS_SUCCESS != status )
5951 {
5952 hdd_deinit_adapter(pHddCtx, pAdapter);
5953 goto err_free_netdev;
5954 }
5955
5956 netif_tx_disable(pAdapter->dev);
5957 netif_carrier_off(pAdapter->dev);
5958
5959 hdd_set_conparam( 1 );
5960 break;
5961 }
5962 case WLAN_HDD_MONITOR:
5963 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005964 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5965 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305966 {
5967 hddLog(VOS_TRACE_LEVEL_FATAL,
5968 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005969 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305970 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005971
5972 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5973 pAdapter->device_mode = session_type;
5974 status = hdd_register_interface( pAdapter, rtnl_held );
5975#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5976 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5977#else
5978 pAdapter->dev->open = hdd_mon_open;
5979 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5980#endif
5981 hdd_init_tx_rx( pAdapter );
5982 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5983 //Set adapter to be used for data tx. It will use either GO or softap.
5984 pAdapter->sessionCtx.monitor.pAdapterForTx =
5985 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005986 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5987 {
5988 pAdapter->sessionCtx.monitor.pAdapterForTx =
5989 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
5990 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005991 /* This workqueue will be used to transmit management packet over
5992 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07005993 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
5994 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
5995 return NULL;
5996 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07005997
Jeff Johnson295189b2012-06-20 16:38:30 -07005998 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
5999 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006000 }
6001 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006002 case WLAN_HDD_FTM:
6003 {
6004 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6005
6006 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306007 {
6008 hddLog(VOS_TRACE_LEVEL_FATAL,
6009 FL("failed to allocate adapter for session %d"), session_type);
6010 return NULL;
6011 }
6012
Jeff Johnson295189b2012-06-20 16:38:30 -07006013 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6014 * message while loading driver in FTM mode. */
6015 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6016 pAdapter->device_mode = session_type;
6017 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306018
6019 hdd_init_tx_rx( pAdapter );
6020
6021 //Stop the Interface TX queue.
6022 netif_tx_disable(pAdapter->dev);
6023 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006024 }
6025 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006026 default:
6027 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306028 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6029 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006030 VOS_ASSERT(0);
6031 return NULL;
6032 }
6033 }
6034
Jeff Johnson295189b2012-06-20 16:38:30 -07006035 if( VOS_STATUS_SUCCESS == status )
6036 {
6037 //Add it to the hdd's session list.
6038 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6039 if( NULL == pHddAdapterNode )
6040 {
6041 status = VOS_STATUS_E_NOMEM;
6042 }
6043 else
6044 {
6045 pHddAdapterNode->pAdapter = pAdapter;
6046 status = hdd_add_adapter_back ( pHddCtx,
6047 pHddAdapterNode );
6048 }
6049 }
6050
6051 if( VOS_STATUS_SUCCESS != status )
6052 {
6053 if( NULL != pAdapter )
6054 {
6055 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6056 pAdapter = NULL;
6057 }
6058 if( NULL != pHddAdapterNode )
6059 {
6060 vos_mem_free( pHddAdapterNode );
6061 }
6062
6063 goto resume_bmps;
6064 }
6065
6066 if(VOS_STATUS_SUCCESS == status)
6067 {
6068 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6069
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006070 //Initialize the WoWL service
6071 if(!hdd_init_wowl(pAdapter))
6072 {
6073 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6074 goto err_free_netdev;
6075 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006076 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006077 return pAdapter;
6078
6079err_free_netdev:
6080 free_netdev(pAdapter->dev);
6081 wlan_hdd_release_intf_addr( pHddCtx,
6082 pAdapter->macAddressCurrent.bytes );
6083
6084resume_bmps:
6085 //If bmps disabled enable it
6086 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6087 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306088 if (pHddCtx->hdd_wlan_suspended)
6089 {
6090 hdd_set_pwrparams(pHddCtx);
6091 }
6092 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006093 }
6094 return NULL;
6095}
6096
6097VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6098 tANI_U8 rtnl_held )
6099{
6100 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6101 VOS_STATUS status;
6102
6103 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6104 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306105 {
6106 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6107 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006108 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306109 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006110
6111 while ( pCurrent->pAdapter != pAdapter )
6112 {
6113 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6114 if( VOS_STATUS_SUCCESS != status )
6115 break;
6116
6117 pCurrent = pNext;
6118 }
6119 pAdapterNode = pCurrent;
6120 if( VOS_STATUS_SUCCESS == status )
6121 {
6122 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6123 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306124
6125#ifdef FEATURE_WLAN_TDLS
6126
6127 /* A Mutex Lock is introduced while changing/initializing the mode to
6128 * protect the concurrent access for the Adapters by TDLS module.
6129 */
6130 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6131 {
6132 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6133 "%s: unable to lock list", __func__);
6134 return VOS_STATUS_E_FAILURE;
6135 }
6136#endif
6137
Jeff Johnson295189b2012-06-20 16:38:30 -07006138 hdd_remove_adapter( pHddCtx, pAdapterNode );
6139 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006140 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006141
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306142#ifdef FEATURE_WLAN_TDLS
6143 mutex_unlock(&pHddCtx->tdls_lock);
6144#endif
6145
Jeff Johnson295189b2012-06-20 16:38:30 -07006146
6147 /* If there is a single session of STA/P2P client, re-enable BMPS */
6148 if ((!vos_concurrent_sessions_running()) &&
6149 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6150 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6151 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306152 if (pHddCtx->hdd_wlan_suspended)
6153 {
6154 hdd_set_pwrparams(pHddCtx);
6155 }
6156 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006157 }
6158
6159 return VOS_STATUS_SUCCESS;
6160 }
6161
6162 return VOS_STATUS_E_FAILURE;
6163}
6164
6165VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6166{
6167 hdd_adapter_list_node_t *pHddAdapterNode;
6168 VOS_STATUS status;
6169
6170 ENTER();
6171
6172 do
6173 {
6174 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6175 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6176 {
6177 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6178 vos_mem_free( pHddAdapterNode );
6179 }
6180 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6181
6182 EXIT();
6183
6184 return VOS_STATUS_SUCCESS;
6185}
6186
6187void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6188{
6189 v_U8_t addIE[1] = {0};
6190
6191 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6192 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6193 eANI_BOOLEAN_FALSE) )
6194 {
6195 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006196 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006197 }
6198
6199 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6200 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6201 eANI_BOOLEAN_FALSE) )
6202 {
6203 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006204 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006205 }
6206
6207 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6208 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6209 eANI_BOOLEAN_FALSE) )
6210 {
6211 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006212 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006213 }
6214}
6215
6216VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6217{
6218 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6219 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6220 union iwreq_data wrqu;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306221 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006222
6223 ENTER();
6224
6225 switch(pAdapter->device_mode)
6226 {
6227 case WLAN_HDD_INFRA_STATION:
6228 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006229 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006230 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6231 {
6232 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6233 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6234 pAdapter->sessionId,
6235 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6236 else
6237 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6238 pAdapter->sessionId,
6239 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6240 //success implies disconnect command got queued up successfully
6241 if(halStatus == eHAL_STATUS_SUCCESS)
6242 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306243 ret = wait_for_completion_interruptible_timeout(
6244 &pAdapter->disconnect_comp_var,
6245 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6246 if (ret <= 0)
6247 {
6248 hddLog(VOS_TRACE_LEVEL_ERROR,
6249 "%s: wait on disconnect_comp_var failed %ld",
6250 __func__, ret);
6251 }
6252 }
6253 else
6254 {
6255 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6256 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006257 }
6258 memset(&wrqu, '\0', sizeof(wrqu));
6259 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6260 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6261 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6262 }
6263 else
6264 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306265 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6266 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006267 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306268#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306269#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306270 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6271#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306272 if (pAdapter->ipv6_notifier_registered)
6273 {
6274 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6275 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6276 pAdapter->ipv6_notifier_registered = false;
6277 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306278#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306279 if (pAdapter->ipv4_notifier_registered)
6280 {
6281 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6282 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6283 pAdapter->ipv4_notifier_registered = false;
6284 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306285#ifdef WLAN_OPEN_SOURCE
6286 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6287#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006288 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6289 {
6290 INIT_COMPLETION(pAdapter->session_close_comp_var);
6291 if (eHAL_STATUS_SUCCESS ==
6292 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6293 hdd_smeCloseSessionCallback, pAdapter))
6294 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306295 unsigned long ret;
6296
Jeff Johnson295189b2012-06-20 16:38:30 -07006297 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306298 ret = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006299 &pAdapter->session_close_comp_var,
6300 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306301 if ( 0 >= ret)
6302 {
6303 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
6304 __func__, ret);
6305 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006306 }
6307 }
6308
6309 break;
6310
6311 case WLAN_HDD_SOFTAP:
6312 case WLAN_HDD_P2P_GO:
6313 //Any softap specific cleanup here...
6314 mutex_lock(&pHddCtx->sap_lock);
6315 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6316 {
6317 VOS_STATUS status;
6318 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6319
6320 //Stop Bss.
6321 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6322 if (VOS_IS_STATUS_SUCCESS(status))
6323 {
6324 hdd_hostapd_state_t *pHostapdState =
6325 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6326
6327 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6328
6329 if (!VOS_IS_STATUS_SUCCESS(status))
6330 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306331 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6332 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006333 }
6334 }
6335 else
6336 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006337 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006338 }
6339 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6340
6341 if (eHAL_STATUS_FAILURE ==
6342 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6343 0, NULL, eANI_BOOLEAN_FALSE))
6344 {
6345 hddLog(LOGE,
6346 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006347 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006348 }
6349
6350 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6351 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6352 eANI_BOOLEAN_FALSE) )
6353 {
6354 hddLog(LOGE,
6355 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6356 }
6357
6358 // Reset WNI_CFG_PROBE_RSP Flags
6359 wlan_hdd_reset_prob_rspies(pAdapter);
6360 kfree(pAdapter->sessionCtx.ap.beacon);
6361 pAdapter->sessionCtx.ap.beacon = NULL;
6362 }
6363 mutex_unlock(&pHddCtx->sap_lock);
6364 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006365
Jeff Johnson295189b2012-06-20 16:38:30 -07006366 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006367#ifdef WLAN_OPEN_SOURCE
6368 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6369#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006370 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006371
Jeff Johnson295189b2012-06-20 16:38:30 -07006372 default:
6373 break;
6374 }
6375
6376 EXIT();
6377 return VOS_STATUS_SUCCESS;
6378}
6379
6380VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6381{
6382 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6383 VOS_STATUS status;
6384 hdd_adapter_t *pAdapter;
6385
6386 ENTER();
6387
6388 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6389
6390 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6391 {
6392 pAdapter = pAdapterNode->pAdapter;
6393 netif_tx_disable(pAdapter->dev);
6394 netif_carrier_off(pAdapter->dev);
6395
6396 hdd_stop_adapter( pHddCtx, pAdapter );
6397
6398 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6399 pAdapterNode = pNext;
6400 }
6401
6402 EXIT();
6403
6404 return VOS_STATUS_SUCCESS;
6405}
6406
Rajeev Kumarf999e582014-01-09 17:33:29 -08006407
6408#ifdef FEATURE_WLAN_BATCH_SCAN
6409/**---------------------------------------------------------------------------
6410
6411 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
6412 structures
6413
6414 \param - pAdapter Pointer to HDD adapter
6415
6416 \return - None
6417
6418 --------------------------------------------------------------------------*/
6419void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
6420{
6421 tHddBatchScanRsp *pNode;
6422 tHddBatchScanRsp *pPrev;
6423
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05306424 if (NULL == pAdapter)
Rajeev Kumarf999e582014-01-09 17:33:29 -08006425 {
Siddharth Bhalb3e9b792014-02-24 15:14:16 +05306426 hddLog(VOS_TRACE_LEVEL_ERROR,
6427 "%s: Adapter context is Null", __func__);
6428 return;
6429 }
6430
6431 pNode = pAdapter->pBatchScanRsp;
6432 while (pNode)
6433 {
6434 pPrev = pNode;
6435 pNode = pNode->pNext;
6436 vos_mem_free((v_VOID_t * )pPrev);
Rajeev Kumarf999e582014-01-09 17:33:29 -08006437 }
6438
6439 pAdapter->pBatchScanRsp = NULL;
6440 pAdapter->numScanList = 0;
6441 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
6442 pAdapter->prev_batch_id = 0;
6443
6444 return;
6445}
6446#endif
6447
6448
Jeff Johnson295189b2012-06-20 16:38:30 -07006449VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6450{
6451 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6452 VOS_STATUS status;
6453 hdd_adapter_t *pAdapter;
6454
6455 ENTER();
6456
6457 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6458
6459 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6460 {
6461 pAdapter = pAdapterNode->pAdapter;
6462 netif_tx_disable(pAdapter->dev);
6463 netif_carrier_off(pAdapter->dev);
6464
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006465 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6466
Jeff Johnson295189b2012-06-20 16:38:30 -07006467 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306468 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6469 {
6470 hdd_wmm_adapter_close( pAdapter );
6471 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6472 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006473
Rajeev Kumarf999e582014-01-09 17:33:29 -08006474#ifdef FEATURE_WLAN_BATCH_SCAN
6475 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6476 {
6477 hdd_deinit_batch_scan(pAdapter);
6478 }
6479#endif
6480
Jeff Johnson295189b2012-06-20 16:38:30 -07006481 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6482 pAdapterNode = pNext;
6483 }
6484
6485 EXIT();
6486
6487 return VOS_STATUS_SUCCESS;
6488}
6489
6490VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6491{
6492 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6493 VOS_STATUS status;
6494 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306495 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006496
6497 ENTER();
6498
6499 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6500
6501 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6502 {
6503 pAdapter = pAdapterNode->pAdapter;
6504
6505 switch(pAdapter->device_mode)
6506 {
6507 case WLAN_HDD_INFRA_STATION:
6508 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006509 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306510
6511 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6512
Jeff Johnson295189b2012-06-20 16:38:30 -07006513 hdd_init_station_mode(pAdapter);
6514 /* Open the gates for HDD to receive Wext commands */
6515 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006516 pHddCtx->scan_info.mScanPending = FALSE;
6517 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006518
6519 //Trigger the initial scan
6520 hdd_wlan_initial_scan(pAdapter);
6521
6522 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306523 if (eConnectionState_Associated == connState ||
6524 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006525 {
6526 union iwreq_data wrqu;
6527 memset(&wrqu, '\0', sizeof(wrqu));
6528 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6529 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6530 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006531 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006532
Jeff Johnson295189b2012-06-20 16:38:30 -07006533 /* indicate disconnected event to nl80211 */
6534 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6535 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006536 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306537 else if (eConnectionState_Connecting == connState)
6538 {
6539 /*
6540 * Indicate connect failure to supplicant if we were in the
6541 * process of connecting
6542 */
6543 cfg80211_connect_result(pAdapter->dev, NULL,
6544 NULL, 0, NULL, 0,
6545 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6546 GFP_KERNEL);
6547 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006548 break;
6549
6550 case WLAN_HDD_SOFTAP:
6551 /* softAP can handle SSR */
6552 break;
6553
6554 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006555 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006556 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006557 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006558 break;
6559
6560 case WLAN_HDD_MONITOR:
6561 /* monitor interface start */
6562 break;
6563 default:
6564 break;
6565 }
6566
6567 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6568 pAdapterNode = pNext;
6569 }
6570
6571 EXIT();
6572
6573 return VOS_STATUS_SUCCESS;
6574}
6575
6576VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6577{
6578 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6579 hdd_adapter_t *pAdapter;
6580 VOS_STATUS status;
6581 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306582 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006583
6584 ENTER();
6585
6586 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6587
6588 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6589 {
6590 pAdapter = pAdapterNode->pAdapter;
6591
6592 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6593 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6594 {
6595 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6596 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6597
6598 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6599 init_completion(&pAdapter->disconnect_comp_var);
6600 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6601 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6602
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306603 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006604 &pAdapter->disconnect_comp_var,
6605 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306606 if (0 >= ret)
6607 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
6608 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07006609
6610 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6611 pHddCtx->isAmpAllowed = VOS_FALSE;
6612 sme_RoamConnect(pHddCtx->hHal,
6613 pAdapter->sessionId, &(pWextState->roamProfile),
6614 &roamId);
6615 }
6616
6617 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6618 pAdapterNode = pNext;
6619 }
6620
6621 EXIT();
6622
6623 return VOS_STATUS_SUCCESS;
6624}
6625
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006626void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6627{
6628 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6629 VOS_STATUS status;
6630 hdd_adapter_t *pAdapter;
6631 hdd_station_ctx_t *pHddStaCtx;
6632 hdd_ap_ctx_t *pHddApCtx;
6633 hdd_hostapd_state_t * pHostapdState;
6634 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6635 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6636 const char *p2pMode = "DEV";
6637 const char *ccMode = "Standalone";
6638 int n;
6639
6640 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6641 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6642 {
6643 pAdapter = pAdapterNode->pAdapter;
6644 switch (pAdapter->device_mode) {
6645 case WLAN_HDD_INFRA_STATION:
6646 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6647 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6648 staChannel = pHddStaCtx->conn_info.operationChannel;
6649 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6650 }
6651 break;
6652 case WLAN_HDD_P2P_CLIENT:
6653 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6654 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6655 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6656 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6657 p2pMode = "CLI";
6658 }
6659 break;
6660 case WLAN_HDD_P2P_GO:
6661 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6662 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6663 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6664 p2pChannel = pHddApCtx->operatingChannel;
6665 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6666 }
6667 p2pMode = "GO";
6668 break;
6669 case WLAN_HDD_SOFTAP:
6670 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6671 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6672 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6673 apChannel = pHddApCtx->operatingChannel;
6674 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6675 }
6676 break;
6677 default:
6678 break;
6679 }
6680 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6681 pAdapterNode = pNext;
6682 }
6683 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6684 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6685 }
6686 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6687 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6688 if (p2pChannel > 0) {
6689 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6690 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6691 }
6692 if (apChannel > 0) {
6693 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6694 apChannel, MAC_ADDR_ARRAY(apBssid));
6695 }
6696
6697 if (p2pChannel > 0 && apChannel > 0) {
6698 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6699 }
6700}
6701
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006702bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006703{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006704 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006705}
6706
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006707/* Once SSR is disabled then it cannot be set. */
6708void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006709{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006710 if (HDD_SSR_DISABLED == isSsrRequired)
6711 return;
6712
Jeff Johnson295189b2012-06-20 16:38:30 -07006713 isSsrRequired = value;
6714}
6715
6716VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6717 hdd_adapter_list_node_t** ppAdapterNode)
6718{
6719 VOS_STATUS status;
6720 spin_lock(&pHddCtx->hddAdapters.lock);
6721 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6722 (hdd_list_node_t**) ppAdapterNode );
6723 spin_unlock(&pHddCtx->hddAdapters.lock);
6724 return status;
6725}
6726
6727VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6728 hdd_adapter_list_node_t* pAdapterNode,
6729 hdd_adapter_list_node_t** pNextAdapterNode)
6730{
6731 VOS_STATUS status;
6732 spin_lock(&pHddCtx->hddAdapters.lock);
6733 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6734 (hdd_list_node_t*) pAdapterNode,
6735 (hdd_list_node_t**)pNextAdapterNode );
6736
6737 spin_unlock(&pHddCtx->hddAdapters.lock);
6738 return status;
6739}
6740
6741VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6742 hdd_adapter_list_node_t* pAdapterNode)
6743{
6744 VOS_STATUS status;
6745 spin_lock(&pHddCtx->hddAdapters.lock);
6746 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6747 &pAdapterNode->node );
6748 spin_unlock(&pHddCtx->hddAdapters.lock);
6749 return status;
6750}
6751
6752VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6753 hdd_adapter_list_node_t** ppAdapterNode)
6754{
6755 VOS_STATUS status;
6756 spin_lock(&pHddCtx->hddAdapters.lock);
6757 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6758 (hdd_list_node_t**) ppAdapterNode );
6759 spin_unlock(&pHddCtx->hddAdapters.lock);
6760 return status;
6761}
6762
6763VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6764 hdd_adapter_list_node_t* pAdapterNode)
6765{
6766 VOS_STATUS status;
6767 spin_lock(&pHddCtx->hddAdapters.lock);
6768 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6769 (hdd_list_node_t*) pAdapterNode );
6770 spin_unlock(&pHddCtx->hddAdapters.lock);
6771 return status;
6772}
6773
6774VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6775 hdd_adapter_list_node_t* pAdapterNode)
6776{
6777 VOS_STATUS status;
6778 spin_lock(&pHddCtx->hddAdapters.lock);
6779 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6780 (hdd_list_node_t*) pAdapterNode );
6781 spin_unlock(&pHddCtx->hddAdapters.lock);
6782 return status;
6783}
6784
6785hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6786 tSirMacAddr macAddr )
6787{
6788 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6789 hdd_adapter_t *pAdapter;
6790 VOS_STATUS status;
6791
6792 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6793
6794 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6795 {
6796 pAdapter = pAdapterNode->pAdapter;
6797
6798 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6799 macAddr, sizeof(tSirMacAddr) ) )
6800 {
6801 return pAdapter;
6802 }
6803 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6804 pAdapterNode = pNext;
6805 }
6806
6807 return NULL;
6808
6809}
6810
6811hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6812{
6813 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6814 hdd_adapter_t *pAdapter;
6815 VOS_STATUS status;
6816
6817 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6818
6819 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6820 {
6821 pAdapter = pAdapterNode->pAdapter;
6822
6823 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6824 IFNAMSIZ ) )
6825 {
6826 return pAdapter;
6827 }
6828 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6829 pAdapterNode = pNext;
6830 }
6831
6832 return NULL;
6833
6834}
6835
6836hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6837{
6838 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6839 hdd_adapter_t *pAdapter;
6840 VOS_STATUS status;
6841
6842 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6843
6844 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6845 {
6846 pAdapter = pAdapterNode->pAdapter;
6847
6848 if( pAdapter && (mode == pAdapter->device_mode) )
6849 {
6850 return pAdapter;
6851 }
6852 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6853 pAdapterNode = pNext;
6854 }
6855
6856 return NULL;
6857
6858}
6859
6860//Remove this function later
6861hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6862{
6863 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6864 hdd_adapter_t *pAdapter;
6865 VOS_STATUS status;
6866
6867 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6868
6869 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6870 {
6871 pAdapter = pAdapterNode->pAdapter;
6872
6873 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6874 {
6875 return pAdapter;
6876 }
6877
6878 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6879 pAdapterNode = pNext;
6880 }
6881
6882 return NULL;
6883
6884}
6885
Jeff Johnson295189b2012-06-20 16:38:30 -07006886/**---------------------------------------------------------------------------
6887
6888 \brief hdd_set_monitor_tx_adapter() -
6889
6890 This API initializes the adapter to be used while transmitting on monitor
6891 adapter.
6892
6893 \param - pHddCtx - Pointer to the HDD context.
6894 pAdapter - Adapter that will used for TX. This can be NULL.
6895 \return - None.
6896 --------------------------------------------------------------------------*/
6897void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6898{
6899 hdd_adapter_t *pMonAdapter;
6900
6901 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6902
6903 if( NULL != pMonAdapter )
6904 {
6905 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6906 }
6907}
Jeff Johnson295189b2012-06-20 16:38:30 -07006908/**---------------------------------------------------------------------------
6909
6910 \brief hdd_select_queue() -
6911
6912 This API returns the operating channel of the requested device mode
6913
6914 \param - pHddCtx - Pointer to the HDD context.
6915 - mode - Device mode for which operating channel is required
6916 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6917 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6918 \return - channel number. "0" id the requested device is not found OR it is not connected.
6919 --------------------------------------------------------------------------*/
6920v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6921{
6922 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6923 VOS_STATUS status;
6924 hdd_adapter_t *pAdapter;
6925 v_U8_t operatingChannel = 0;
6926
6927 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6928
6929 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6930 {
6931 pAdapter = pAdapterNode->pAdapter;
6932
6933 if( mode == pAdapter->device_mode )
6934 {
6935 switch(pAdapter->device_mode)
6936 {
6937 case WLAN_HDD_INFRA_STATION:
6938 case WLAN_HDD_P2P_CLIENT:
6939 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6940 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6941 break;
6942 case WLAN_HDD_SOFTAP:
6943 case WLAN_HDD_P2P_GO:
6944 /*softap connection info */
6945 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6946 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6947 break;
6948 default:
6949 break;
6950 }
6951
6952 break; //Found the device of interest. break the loop
6953 }
6954
6955 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6956 pAdapterNode = pNext;
6957 }
6958 return operatingChannel;
6959}
6960
6961#ifdef WLAN_FEATURE_PACKET_FILTERING
6962/**---------------------------------------------------------------------------
6963
6964 \brief hdd_set_multicast_list() -
6965
6966 This used to set the multicast address list.
6967
6968 \param - dev - Pointer to the WLAN device.
6969 - skb - Pointer to OS packet (sk_buff).
6970 \return - success/fail
6971
6972 --------------------------------------------------------------------------*/
6973static void hdd_set_multicast_list(struct net_device *dev)
6974{
6975 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006976 int mc_count;
6977 int i = 0;
6978 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306979
6980 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006981 {
6982 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306983 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006984 return;
6985 }
6986
6987 if (dev->flags & IFF_ALLMULTI)
6988 {
6989 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006990 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306991 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07006992 }
6993 else
6994 {
6995 mc_count = netdev_mc_count(dev);
6996 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006997 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07006998 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
6999 {
7000 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007001 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307002 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007003 return;
7004 }
7005
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307006 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007007
7008 netdev_for_each_mc_addr(ha, dev) {
7009 if (i == mc_count)
7010 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307011 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7012 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007013 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007014 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307015 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007016 i++;
7017 }
7018 }
7019 return;
7020}
7021#endif
7022
7023/**---------------------------------------------------------------------------
7024
7025 \brief hdd_select_queue() -
7026
7027 This function is registered with the Linux OS for network
7028 core to decide which queue to use first.
7029
7030 \param - dev - Pointer to the WLAN device.
7031 - skb - Pointer to OS packet (sk_buff).
7032 \return - ac, Queue Index/access category corresponding to UP in IP header
7033
7034 --------------------------------------------------------------------------*/
7035v_U16_t hdd_select_queue(struct net_device *dev,
7036 struct sk_buff *skb)
7037{
7038 return hdd_wmm_select_queue(dev, skb);
7039}
7040
7041
7042/**---------------------------------------------------------------------------
7043
7044 \brief hdd_wlan_initial_scan() -
7045
7046 This function triggers the initial scan
7047
7048 \param - pAdapter - Pointer to the HDD adapter.
7049
7050 --------------------------------------------------------------------------*/
7051void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7052{
7053 tCsrScanRequest scanReq;
7054 tCsrChannelInfo channelInfo;
7055 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007056 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007057 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7058
7059 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7060 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7061 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7062
7063 if(sme_Is11dSupported(pHddCtx->hHal))
7064 {
7065 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7066 if ( HAL_STATUS_SUCCESS( halStatus ) )
7067 {
7068 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7069 if( !scanReq.ChannelInfo.ChannelList )
7070 {
7071 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7072 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007073 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007074 return;
7075 }
7076 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7077 channelInfo.numOfChannels);
7078 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7079 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007080 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007081 }
7082
7083 scanReq.scanType = eSIR_PASSIVE_SCAN;
7084 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7085 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7086 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7087 }
7088 else
7089 {
7090 scanReq.scanType = eSIR_ACTIVE_SCAN;
7091 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7092 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7093 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7094 }
7095
7096 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7097 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7098 {
7099 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7100 __func__, halStatus );
7101 }
7102
7103 if(sme_Is11dSupported(pHddCtx->hHal))
7104 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7105}
7106
Jeff Johnson295189b2012-06-20 16:38:30 -07007107/**---------------------------------------------------------------------------
7108
7109 \brief hdd_full_power_callback() - HDD full power callback function
7110
7111 This is the function invoked by SME to inform the result of a full power
7112 request issued by HDD
7113
7114 \param - callbackcontext - Pointer to cookie
7115 \param - status - result of request
7116
7117 \return - None
7118
7119 --------------------------------------------------------------------------*/
7120static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7121{
Jeff Johnson72a40512013-12-19 10:14:15 -08007122 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007123
7124 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307125 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007126
7127 if (NULL == callbackContext)
7128 {
7129 hddLog(VOS_TRACE_LEVEL_ERROR,
7130 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007131 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007132 return;
7133 }
7134
Jeff Johnson72a40512013-12-19 10:14:15 -08007135 /* there is a race condition that exists between this callback
7136 function and the caller since the caller could time out either
7137 before or while this code is executing. we use a spinlock to
7138 serialize these actions */
7139 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007140
7141 if (POWER_CONTEXT_MAGIC != pContext->magic)
7142 {
7143 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007144 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007145 hddLog(VOS_TRACE_LEVEL_WARN,
7146 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007147 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007148 return;
7149 }
7150
Jeff Johnson72a40512013-12-19 10:14:15 -08007151 /* context is valid so caller is still waiting */
7152
7153 /* paranoia: invalidate the magic */
7154 pContext->magic = 0;
7155
7156 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007157 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007158
7159 /* serialization is complete */
7160 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007161}
7162
7163/**---------------------------------------------------------------------------
7164
7165 \brief hdd_wlan_exit() - HDD WLAN exit function
7166
7167 This is the driver exit point (invoked during rmmod)
7168
7169 \param - pHddCtx - Pointer to the HDD Context
7170
7171 \return - None
7172
7173 --------------------------------------------------------------------------*/
7174void hdd_wlan_exit(hdd_context_t *pHddCtx)
7175{
7176 eHalStatus halStatus;
7177 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7178 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307179 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007180 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007181 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007182 long lrc;
7183
7184 ENTER();
7185
Jeff Johnson88ba7742013-02-27 14:36:02 -08007186 if (VOS_FTM_MODE != hdd_get_conparam())
7187 {
7188 // Unloading, restart logic is no more required.
7189 wlan_hdd_restart_deinit(pHddCtx);
7190 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007191
Jeff Johnson295189b2012-06-20 16:38:30 -07007192 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007193 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007194 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007195 {
7196 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
7197 WLAN_HDD_INFRA_STATION);
7198 if (pAdapter == NULL)
7199 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
7200
7201 if (pAdapter != NULL)
7202 {
7203 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
7204 hdd_UnregisterWext(pAdapter->dev);
7205 }
7206 }
7207 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007208
Jeff Johnson295189b2012-06-20 16:38:30 -07007209 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08007210 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307211 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007212 wlan_hdd_ftm_close(pHddCtx);
7213 goto free_hdd_ctx;
7214 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007215 //Stop the Interface TX queue.
7216 //netif_tx_disable(pWlanDev);
7217 //netif_carrier_off(pWlanDev);
7218
Jeff Johnson295189b2012-06-20 16:38:30 -07007219 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7220 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307221 hddLog(VOS_TRACE_LEVEL_INFO,"%s: SAP MODE",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007222 pAdapter = hdd_get_adapter(pHddCtx,
7223 WLAN_HDD_SOFTAP);
7224 }
7225 else
7226 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007227 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007228 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307229 hddLog(VOS_TRACE_LEVEL_INFO,"%s: STA MODE",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007230 pAdapter = hdd_get_adapter(pHddCtx,
7231 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007232 if (pAdapter == NULL)
7233 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007234 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007235 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307236
7237 if(NULL == pAdapter)
7238 {
7239 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: pAdapter is NULL",__func__);
7240 goto free_hdd_ctx;
7241 }
7242
Jeff Johnson295189b2012-06-20 16:38:30 -07007243 /* DeRegister with platform driver as client for Suspend/Resume */
7244 vosStatus = hddDeregisterPmOps(pHddCtx);
7245 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7246 {
7247 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7248 VOS_ASSERT(0);
7249 }
7250
7251 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7252 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7253 {
7254 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7255 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007256
7257 // Cancel any outstanding scan requests. We are about to close all
7258 // of our adapters, but an adapter structure is what SME passes back
7259 // to our callback function. Hence if there are any outstanding scan
7260 // requests then there is a race condition between when the adapter
7261 // is closed and when the callback is invoked. We try to resolve that
7262 // race condition here by canceling any outstanding scans before we
7263 // close the adapters.
7264 // Note that the scans may be cancelled in an asynchronous manner, so
7265 // ideally there needs to be some kind of synchronization. Rather than
7266 // introduce a new synchronization here, we will utilize the fact that
7267 // we are about to Request Full Power, and since that is synchronized,
7268 // the expectation is that by the time Request Full Power has completed,
7269 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007270 if (NULL != pAdapter)
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05307271 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, eCSR_SCAN_ABORT_DEFAULT);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007272 else
7273 hddLog(VOS_TRACE_LEVEL_ERROR,
7274 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007275
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007276 //Stop the traffic monitor timer
7277 if ( VOS_TIMER_STATE_RUNNING ==
7278 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7279 {
7280 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7281 }
7282
7283 // Destroy the traffic monitor timer
7284 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7285 &pHddCtx->tx_rx_trafficTmr)))
7286 {
7287 hddLog(VOS_TRACE_LEVEL_ERROR,
7288 "%s: Cannot deallocate Traffic monitor timer", __func__);
7289 }
7290
Jeff Johnson295189b2012-06-20 16:38:30 -07007291 //Disable IMPS/BMPS as we do not want the device to enter any power
7292 //save mode during shutdown
7293 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7294 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7295 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7296
7297 //Ensure that device is in full power as we will touch H/W during vos_Stop
7298 init_completion(&powerContext.completion);
7299 powerContext.magic = POWER_CONTEXT_MAGIC;
7300
7301 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7302 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7303
7304 if (eHAL_STATUS_SUCCESS != halStatus)
7305 {
7306 if (eHAL_STATUS_PMC_PENDING == halStatus)
7307 {
7308 /* request was sent -- wait for the response */
7309 lrc = wait_for_completion_interruptible_timeout(
7310 &powerContext.completion,
7311 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007312 if (lrc <= 0)
7313 {
7314 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007315 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007316 }
7317 }
7318 else
7319 {
7320 hddLog(VOS_TRACE_LEVEL_ERROR,
7321 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007322 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007323 /* continue -- need to clean up as much as possible */
7324 }
7325 }
7326
Jeff Johnson72a40512013-12-19 10:14:15 -08007327 /* either we never sent a request, we sent a request and received a
7328 response or we sent a request and timed out. if we never sent a
7329 request or if we sent a request and got a response, we want to
7330 clear the magic out of paranoia. if we timed out there is a
7331 race condition such that the callback function could be
7332 executing at the same time we are. of primary concern is if the
7333 callback function had already verified the "magic" but had not
7334 yet set the completion variable when a timeout occurred. we
7335 serialize these activities by invalidating the magic while
7336 holding a shared spinlock which will cause us to block if the
7337 callback is currently executing */
7338 spin_lock(&hdd_context_lock);
7339 powerContext.magic = 0;
7340 spin_unlock(&hdd_context_lock);
7341
Yue Ma0d4891e2013-08-06 17:01:45 -07007342 hdd_debugfs_exit(pHddCtx);
7343
Jeff Johnson295189b2012-06-20 16:38:30 -07007344 // Unregister the Net Device Notifier
7345 unregister_netdevice_notifier(&hdd_netdev_notifier);
7346
Jeff Johnson295189b2012-06-20 16:38:30 -07007347 hdd_stop_all_adapters( pHddCtx );
7348
Jeff Johnson295189b2012-06-20 16:38:30 -07007349#ifdef WLAN_BTAMP_FEATURE
7350 vosStatus = WLANBAP_Stop(pVosContext);
7351 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7352 {
7353 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7354 "%s: Failed to stop BAP",__func__);
7355 }
7356#endif //WLAN_BTAMP_FEATURE
7357
7358 //Stop all the modules
7359 vosStatus = vos_stop( pVosContext );
7360 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7361 {
7362 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7363 "%s: Failed to stop VOSS",__func__);
7364 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7365 }
7366
Jeff Johnson295189b2012-06-20 16:38:30 -07007367 //Assert Deep sleep signal now to put Libra HW in lowest power state
7368 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7369 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7370
7371 //Vote off any PMIC voltage supplies
7372 vos_chipPowerDown(NULL, NULL, NULL);
7373
7374 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7375
Leo Chang59cdc7e2013-07-10 10:08:21 -07007376
Jeff Johnson295189b2012-06-20 16:38:30 -07007377 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007378 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007379
7380 //Close the scheduler before calling vos_close to make sure no thread is
7381 // scheduled after the each module close is called i.e after all the data
7382 // structures are freed.
7383 vosStatus = vos_sched_close( pVosContext );
7384 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7385 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7386 "%s: Failed to close VOSS Scheduler",__func__);
7387 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7388 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007389#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007390#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7391 /* Destroy the wake lock */
7392 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7393#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007394 /* Destroy the wake lock */
7395 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007396#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007397
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307398#ifdef CONFIG_ENABLE_LINUX_REG
7399 vosStatus = vos_nv_close();
7400 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7401 {
7402 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7403 "%s: Failed to close NV", __func__);
7404 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7405 }
7406#endif
7407
Jeff Johnson295189b2012-06-20 16:38:30 -07007408 //Close VOSS
7409 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7410 vos_close(pVosContext);
7411
Jeff Johnson295189b2012-06-20 16:38:30 -07007412 //Close Watchdog
7413 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7414 vos_watchdog_close(pVosContext);
7415
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307416 //Clean up HDD Nlink Service
7417 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007418#ifdef WLAN_KD_READY_NOTIFIER
7419 nl_srv_exit(pHddCtx->ptt_pid);
7420#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307421 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007422#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307423
Jeff Johnson295189b2012-06-20 16:38:30 -07007424 /* Cancel the vote for XO Core ON.
7425 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7426 * exited at this point
7427 */
7428 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007429 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007430 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7431 {
7432 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7433 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007434 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007435 }
7436
7437 hdd_close_all_adapters( pHddCtx );
7438
7439
7440 //Free up dynamically allocated members inside HDD Adapter
7441 kfree(pHddCtx->cfg_ini);
7442 pHddCtx->cfg_ini= NULL;
7443
7444 /* free the power on lock from platform driver */
7445 if (free_riva_power_on_lock("wlan"))
7446 {
7447 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7448 __func__);
7449 }
7450
Jeff Johnson88ba7742013-02-27 14:36:02 -08007451free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007452 /* FTM mode, WIPHY did not registered
7453 If un-register here, system crash will happen */
7454 if (VOS_FTM_MODE != hdd_get_conparam())
7455 {
7456 wiphy_unregister(wiphy) ;
7457 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007458 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007459 if (hdd_is_ssr_required())
7460 {
7461 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007462 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007463 msleep(5000);
7464 }
7465 hdd_set_ssr_required (VOS_FALSE);
7466}
7467
7468
7469/**---------------------------------------------------------------------------
7470
7471 \brief hdd_update_config_from_nv() - Function to update the contents of
7472 the running configuration with parameters taken from NV storage
7473
7474 \param - pHddCtx - Pointer to the HDD global context
7475
7476 \return - VOS_STATUS_SUCCESS if successful
7477
7478 --------------------------------------------------------------------------*/
7479static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7480{
Jeff Johnson295189b2012-06-20 16:38:30 -07007481 v_BOOL_t itemIsValid = VOS_FALSE;
7482 VOS_STATUS status;
7483 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7484 v_U8_t macLoop;
7485
7486 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7487 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7488 if(status != VOS_STATUS_SUCCESS)
7489 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007490 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007491 return VOS_STATUS_E_FAILURE;
7492 }
7493
7494 if (itemIsValid == VOS_TRUE)
7495 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007496 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007497 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7498 VOS_MAX_CONCURRENCY_PERSONA);
7499 if(status != VOS_STATUS_SUCCESS)
7500 {
7501 /* Get MAC from NV fail, not update CFG info
7502 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007503 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007504 return VOS_STATUS_E_FAILURE;
7505 }
7506
7507 /* If first MAC is not valid, treat all others are not valid
7508 * Then all MACs will be got from ini file */
7509 if(vos_is_macaddr_zero(&macFromNV[0]))
7510 {
7511 /* MAC address in NV file is not configured yet */
7512 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7513 return VOS_STATUS_E_INVAL;
7514 }
7515
7516 /* Get MAC address from NV, update CFG info */
7517 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7518 {
7519 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7520 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307521 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07007522 /* This MAC is not valid, skip it
7523 * This MAC will be got from ini file */
7524 }
7525 else
7526 {
7527 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7528 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7529 VOS_MAC_ADDR_SIZE);
7530 }
7531 }
7532 }
7533 else
7534 {
7535 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7536 return VOS_STATUS_E_FAILURE;
7537 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007538
Jeff Johnson295189b2012-06-20 16:38:30 -07007539
7540 return VOS_STATUS_SUCCESS;
7541}
7542
7543/**---------------------------------------------------------------------------
7544
7545 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7546
7547 \param - pAdapter - Pointer to the HDD
7548
7549 \return - None
7550
7551 --------------------------------------------------------------------------*/
7552VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7553{
7554 eHalStatus halStatus;
7555 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307556 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007557
Jeff Johnson295189b2012-06-20 16:38:30 -07007558
7559 // Send ready indication to the HDD. This will kick off the MAC
7560 // into a 'running' state and should kick off an initial scan.
7561 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7562 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7563 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307564 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007565 "code %08d [x%08x]",__func__, halStatus, halStatus );
7566 return VOS_STATUS_E_FAILURE;
7567 }
7568
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307569 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007570 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7571 // And RIVA will crash
7572 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7573 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307574 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7575 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7576
7577
Jeff Johnson295189b2012-06-20 16:38:30 -07007578 return VOS_STATUS_SUCCESS;
7579}
7580
Jeff Johnson295189b2012-06-20 16:38:30 -07007581/* wake lock APIs for HDD */
7582void hdd_prevent_suspend(void)
7583{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007584#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007585 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007586#else
7587 wcnss_prevent_suspend();
7588#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007589}
7590
7591void hdd_allow_suspend(void)
7592{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007593#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007594 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007595#else
7596 wcnss_allow_suspend();
7597#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007598}
7599
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05307600void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007601{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007602#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007603 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007604#else
7605 /* Do nothing as there is no API in wcnss for timeout*/
7606#endif
7607}
7608
Jeff Johnson295189b2012-06-20 16:38:30 -07007609/**---------------------------------------------------------------------------
7610
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007611 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7612 information between Host and Riva
7613
7614 This function gets reported version of FW
7615 It also finds the version of Riva headers used to compile the host
7616 It compares the above two and prints a warning if they are different
7617 It gets the SW and HW version string
7618 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7619 indicating the features they support through a bitmap
7620
7621 \param - pHddCtx - Pointer to HDD context
7622
7623 \return - void
7624
7625 --------------------------------------------------------------------------*/
7626
7627void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7628{
7629
7630 tSirVersionType versionCompiled;
7631 tSirVersionType versionReported;
7632 tSirVersionString versionString;
7633 tANI_U8 fwFeatCapsMsgSupported = 0;
7634 VOS_STATUS vstatus;
7635
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007636 memset(&versionCompiled, 0, sizeof(versionCompiled));
7637 memset(&versionReported, 0, sizeof(versionReported));
7638
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007639 /* retrieve and display WCNSS version information */
7640 do {
7641
7642 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7643 &versionCompiled);
7644 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7645 {
7646 hddLog(VOS_TRACE_LEVEL_FATAL,
7647 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007648 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007649 break;
7650 }
7651
7652 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7653 &versionReported);
7654 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7655 {
7656 hddLog(VOS_TRACE_LEVEL_FATAL,
7657 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007658 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007659 break;
7660 }
7661
7662 if ((versionCompiled.major != versionReported.major) ||
7663 (versionCompiled.minor != versionReported.minor) ||
7664 (versionCompiled.version != versionReported.version) ||
7665 (versionCompiled.revision != versionReported.revision))
7666 {
7667 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7668 "Host expected %u.%u.%u.%u\n",
7669 WLAN_MODULE_NAME,
7670 (int)versionReported.major,
7671 (int)versionReported.minor,
7672 (int)versionReported.version,
7673 (int)versionReported.revision,
7674 (int)versionCompiled.major,
7675 (int)versionCompiled.minor,
7676 (int)versionCompiled.version,
7677 (int)versionCompiled.revision);
7678 }
7679 else
7680 {
7681 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7682 WLAN_MODULE_NAME,
7683 (int)versionReported.major,
7684 (int)versionReported.minor,
7685 (int)versionReported.version,
7686 (int)versionReported.revision);
7687 }
7688
7689 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7690 versionString,
7691 sizeof(versionString));
7692 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7693 {
7694 hddLog(VOS_TRACE_LEVEL_FATAL,
7695 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007696 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007697 break;
7698 }
7699
7700 pr_info("%s: WCNSS software version %s\n",
7701 WLAN_MODULE_NAME, versionString);
7702
7703 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7704 versionString,
7705 sizeof(versionString));
7706 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7707 {
7708 hddLog(VOS_TRACE_LEVEL_FATAL,
7709 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007710 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007711 break;
7712 }
7713
7714 pr_info("%s: WCNSS hardware version %s\n",
7715 WLAN_MODULE_NAME, versionString);
7716
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007717 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7718 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007719 send the message only if it the riva is 1.1
7720 minor numbers for different riva branches:
7721 0 -> (1.0)Mainline Build
7722 1 -> (1.1)Mainline Build
7723 2->(1.04) Stability Build
7724 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007725 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007726 ((versionReported.minor>=1) && (versionReported.version>=1)))
7727 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7728 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007729
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007730 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007731 {
7732#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7733 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7734 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7735#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007736 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7737 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7738 {
7739 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7740 }
7741
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007742 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007743 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007744
7745 } while (0);
7746
7747}
7748
7749/**---------------------------------------------------------------------------
7750
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307751 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7752
7753 \param - pHddCtx - Pointer to the hdd context
7754
7755 \return - true if hardware supports 5GHz
7756
7757 --------------------------------------------------------------------------*/
7758static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7759{
7760 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7761 * then hardware support 5Ghz.
7762 */
7763 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7764 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05307765 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307766 return true;
7767 }
7768 else
7769 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05307770 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307771 __func__);
7772 return false;
7773 }
7774}
7775
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307776/**---------------------------------------------------------------------------
7777
7778 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
7779 generate function
7780
7781 This is generate the random mac address for WLAN interface
7782
7783 \param - pHddCtx - Pointer to HDD context
7784 idx - Start interface index to get auto
7785 generated mac addr.
7786 mac_addr - Mac address
7787
7788 \return - 0 for success, < 0 for failure
7789
7790 --------------------------------------------------------------------------*/
7791
7792static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
7793 int idx, v_MACADDR_t mac_addr)
7794{
7795 int i;
7796 unsigned int serialno;
7797 serialno = wcnss_get_serial_number();
7798
7799 if (0 != serialno)
7800 {
7801 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7802 bytes of the serial number that can be used to generate
7803 the other 3 bytes of the MAC address. Mask off all but
7804 the lower 3 bytes (this will also make sure we don't
7805 overflow in the next step) */
7806 serialno &= 0x00FFFFFF;
7807
7808 /* we need a unique address for each session */
7809 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7810
7811 /* autogen other Mac addresses */
7812 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7813 {
7814 /* start with the entire default address */
7815 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
7816 /* then replace the lower 3 bytes */
7817 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7818 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7819 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7820
7821 serialno++;
7822 hddLog(VOS_TRACE_LEVEL_ERROR,
7823 "%s: Derived Mac Addr: "
7824 MAC_ADDRESS_STR, __func__,
7825 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
7826 }
7827
7828 }
7829 else
7830 {
7831 hddLog(LOGE, FL("Failed to Get Serial NO"));
7832 return -1;
7833 }
7834 return 0;
7835}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307836
7837/**---------------------------------------------------------------------------
7838
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05307839 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
7840 completed to flush out the scan results
7841
7842 11d scan is done during driver load and is a passive scan on all
7843 channels supported by the device, 11d scans may find some APs on
7844 frequencies which are forbidden to be used in the regulatory domain
7845 the device is operating in. If these APs are notified to the supplicant
7846 it may try to connect to these APs, thus flush out all the scan results
7847 which are present in SME after 11d scan is done.
7848
7849 \return - eHalStatus
7850
7851 --------------------------------------------------------------------------*/
7852static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
7853 tANI_U32 scanId, eCsrScanStatus status)
7854{
7855 ENTER();
7856
7857 sme_ScanFlushResult(halHandle, 0);
7858
7859 EXIT();
7860
7861 return eHAL_STATUS_SUCCESS;
7862}
7863
7864/**---------------------------------------------------------------------------
7865
Jeff Johnson295189b2012-06-20 16:38:30 -07007866 \brief hdd_wlan_startup() - HDD init function
7867
7868 This is the driver startup code executed once a WLAN device has been detected
7869
7870 \param - dev - Pointer to the underlying device
7871
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007872 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007873
7874 --------------------------------------------------------------------------*/
7875
7876int hdd_wlan_startup(struct device *dev )
7877{
7878 VOS_STATUS status;
7879 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007880 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007881 hdd_context_t *pHddCtx = NULL;
7882 v_CONTEXT_t pVosContext= NULL;
7883#ifdef WLAN_BTAMP_FEATURE
7884 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7885 WLANBAP_ConfigType btAmpConfig;
7886 hdd_config_t *pConfig;
7887#endif
7888 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007889 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307890 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07007891
7892 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007893 /*
7894 * cfg80211: wiphy allocation
7895 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307896 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007897
7898 if(wiphy == NULL)
7899 {
7900 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007901 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007902 }
7903
7904 pHddCtx = wiphy_priv(wiphy);
7905
Jeff Johnson295189b2012-06-20 16:38:30 -07007906 //Initialize the adapter context to zeros.
7907 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7908
Jeff Johnson295189b2012-06-20 16:38:30 -07007909 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007910 hdd_prevent_suspend();
7911 pHddCtx->isLoadUnloadInProgress = TRUE;
7912
7913 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7914
7915 /*Get vos context here bcoz vos_open requires it*/
7916 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7917
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007918 if(pVosContext == NULL)
7919 {
7920 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7921 goto err_free_hdd_context;
7922 }
7923
Jeff Johnson295189b2012-06-20 16:38:30 -07007924 //Save the Global VOSS context in adapter context for future.
7925 pHddCtx->pvosContext = pVosContext;
7926
7927 //Save the adapter context in global context for future.
7928 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7929
Jeff Johnson295189b2012-06-20 16:38:30 -07007930 pHddCtx->parent_dev = dev;
7931
7932 init_completion(&pHddCtx->full_pwr_comp_var);
7933 init_completion(&pHddCtx->standby_comp_var);
7934 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007935 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007936 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307937 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007938
7939#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007940 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007941#else
7942 init_completion(&pHddCtx->driver_crda_req);
7943#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007944
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307945 spin_lock_init(&pHddCtx->schedScan_lock);
7946
Jeff Johnson295189b2012-06-20 16:38:30 -07007947 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7948
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307949#ifdef FEATURE_WLAN_TDLS
7950 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7951 * invoked by other instances also) to protect the concurrent
7952 * access for the Adapters by TDLS module.
7953 */
7954 mutex_init(&pHddCtx->tdls_lock);
7955#endif
7956
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307957 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007958 // Load all config first as TL config is needed during vos_open
7959 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7960 if(pHddCtx->cfg_ini == NULL)
7961 {
7962 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7963 goto err_free_hdd_context;
7964 }
7965
7966 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7967
7968 // Read and parse the qcom_cfg.ini file
7969 status = hdd_parse_config_ini( pHddCtx );
7970 if ( VOS_STATUS_SUCCESS != status )
7971 {
7972 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7973 __func__, WLAN_INI_FILE);
7974 goto err_config;
7975 }
Arif Hussaind5218912013-12-05 01:10:55 -08007976#ifdef MEMORY_DEBUG
7977 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
7978 vos_mem_init();
7979
7980 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
7981 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
7982#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007983
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307984 /* INI has been read, initialise the configuredMcastBcastFilter with
7985 * INI value as this will serve as the default value
7986 */
7987 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7988 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7989 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307990
7991 if (false == hdd_is_5g_supported(pHddCtx))
7992 {
7993 //5Ghz is not supported.
7994 if (1 != pHddCtx->cfg_ini->nBandCapability)
7995 {
7996 hddLog(VOS_TRACE_LEVEL_INFO,
7997 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
7998 pHddCtx->cfg_ini->nBandCapability = 1;
7999 }
8000 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308001
8002 /* If SNR Monitoring is enabled, FW has to parse all beacons
8003 * for calcaluting and storing the average SNR, so set Nth beacon
8004 * filter to 1 to enable FW to parse all the beaocons
8005 */
8006 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8007 {
8008 /* The log level is deliberately set to WARN as overriding
8009 * nthBeaconFilter to 1 will increase power cosumption and this
8010 * might just prove helpful to detect the power issue.
8011 */
8012 hddLog(VOS_TRACE_LEVEL_WARN,
8013 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8014 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8015 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008016 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308017 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008018 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008019 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008020 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008021 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8022 {
8023 hddLog(VOS_TRACE_LEVEL_FATAL,
8024 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8025 goto err_config;
8026 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008027 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008028
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008029 // Update VOS trace levels based upon the cfg.ini
8030 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8031 pHddCtx->cfg_ini->vosTraceEnableBAP);
8032 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8033 pHddCtx->cfg_ini->vosTraceEnableTL);
8034 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8035 pHddCtx->cfg_ini->vosTraceEnableWDI);
8036 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8037 pHddCtx->cfg_ini->vosTraceEnableHDD);
8038 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8039 pHddCtx->cfg_ini->vosTraceEnableSME);
8040 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8041 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308042 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8043 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008044 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8045 pHddCtx->cfg_ini->vosTraceEnableWDA);
8046 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8047 pHddCtx->cfg_ini->vosTraceEnableSYS);
8048 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8049 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008050 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8051 pHddCtx->cfg_ini->vosTraceEnableSAP);
8052 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8053 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008054
Jeff Johnson295189b2012-06-20 16:38:30 -07008055 // Update WDI trace levels based upon the cfg.ini
8056 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8057 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8058 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8059 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8060 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8061 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8062 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8063 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008064
Jeff Johnson88ba7742013-02-27 14:36:02 -08008065 if (VOS_FTM_MODE == hdd_get_conparam())
8066 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008067 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8068 {
8069 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8070 goto err_free_hdd_context;
8071 }
8072 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
8073 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008074 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008075
Jeff Johnson88ba7742013-02-27 14:36:02 -08008076 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008077 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8078 {
8079 status = vos_watchdog_open(pVosContext,
8080 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8081
8082 if(!VOS_IS_STATUS_SUCCESS( status ))
8083 {
8084 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308085 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008086 }
8087 }
8088
8089 pHddCtx->isLogpInProgress = FALSE;
8090 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8091
Jeff Johnson295189b2012-06-20 16:38:30 -07008092 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
8093 if(!VOS_IS_STATUS_SUCCESS(status))
8094 {
8095 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008096 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008097 }
8098
Amar Singhala49cbc52013-10-08 18:37:44 -07008099#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008100 /* initialize the NV module. This is required so that
8101 we can initialize the channel information in wiphy
8102 from the NV.bin data. The channel information in
8103 wiphy needs to be initialized before wiphy registration */
8104
8105 status = vos_nv_open();
8106 if (!VOS_IS_STATUS_SUCCESS(status))
8107 {
8108 /* NV module cannot be initialized */
8109 hddLog( VOS_TRACE_LEVEL_FATAL,
8110 "%s: vos_nv_open failed", __func__);
8111 goto err_clkvote;
8112 }
8113
8114 status = vos_init_wiphy_from_nv_bin();
8115 if (!VOS_IS_STATUS_SUCCESS(status))
8116 {
8117 /* NV module cannot be initialized */
8118 hddLog( VOS_TRACE_LEVEL_FATAL,
8119 "%s: vos_init_wiphy failed", __func__);
8120 goto err_vos_nv_close;
8121 }
8122
Amar Singhala49cbc52013-10-08 18:37:44 -07008123#endif
8124
Jeff Johnson295189b2012-06-20 16:38:30 -07008125 status = vos_open( &pVosContext, 0);
8126 if ( !VOS_IS_STATUS_SUCCESS( status ))
8127 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008128 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308129 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008130 }
8131
Jeff Johnson295189b2012-06-20 16:38:30 -07008132 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8133
8134 if ( NULL == pHddCtx->hHal )
8135 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008136 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008137 goto err_vosclose;
8138 }
8139
Mihir Shetee1093ba2014-01-21 20:13:32 +05308140#ifdef CONFIG_ENABLE_LINUX_REG
8141 /* registration of wiphy dev with cfg80211 */
8142 if (0 > wlan_hdd_cfg80211_register(wiphy))
8143 {
8144 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8145 goto err_vosclose;
8146 }
8147
8148 status = wlan_hdd_init_channels(pHddCtx);
8149 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8150 {
8151 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8152 __func__);
8153 goto err_wiphy_unregister;
8154 }
8155#endif
8156
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008157 status = vos_preStart( pHddCtx->pvosContext );
8158 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8159 {
8160 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308161 goto err_wiphy_unregister;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008162 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008163
Arif Hussaineaf68602013-12-30 23:10:44 -08008164 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8165 {
8166 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8167 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8168 __func__, enable_dfs_chan_scan);
8169 }
8170 if (0 == enable_11d || 1 == enable_11d)
8171 {
8172 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8173 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8174 __func__, enable_11d);
8175 }
8176
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008177 /* Note that the vos_preStart() sequence triggers the cfg download.
8178 The cfg download must occur before we update the SME config
8179 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008180 status = hdd_set_sme_config( pHddCtx );
8181
8182 if ( VOS_STATUS_SUCCESS != status )
8183 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008184 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308185 goto err_wiphy_unregister;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008186 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008187
8188 //Initialize the WMM module
8189 status = hdd_wmm_init(pHddCtx);
8190 if (!VOS_IS_STATUS_SUCCESS(status))
8191 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008192 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308193 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008194 }
8195
Jeff Johnson295189b2012-06-20 16:38:30 -07008196 /* In the integrated architecture we update the configuration from
8197 the INI file and from NV before vOSS has been started so that
8198 the final contents are available to send down to the cCPU */
8199
8200 // Apply the cfg.ini to cfg.dat
8201 if (FALSE == hdd_update_config_dat(pHddCtx))
8202 {
8203 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mihir Shetee1093ba2014-01-21 20:13:32 +05308204 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008205 }
8206
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308207 // Get mac addr from platform driver
8208 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8209
8210 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008211 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308212 /* Store the mac addr for first interface */
8213 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8214
8215 hddLog(VOS_TRACE_LEVEL_ERROR,
8216 "%s: WLAN Mac Addr: "
8217 MAC_ADDRESS_STR, __func__,
8218 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8219
8220 /* Here, passing Arg2 as 1 because we do not want to change the
8221 last 3 bytes (means non OUI bytes) of first interface mac
8222 addr.
8223 */
8224 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8225 {
8226 hddLog(VOS_TRACE_LEVEL_ERROR,
8227 "%s: Failed to generate wlan interface mac addr "
8228 "using MAC from ini file ", __func__);
8229 }
8230 }
8231 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8232 {
8233 // Apply the NV to cfg.dat
8234 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008235#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8236 /* There was not a valid set of MAC Addresses in NV. See if the
8237 default addresses were modified by the cfg.ini settings. If so,
8238 we'll use them, but if not, we'll autogenerate a set of MAC
8239 addresses based upon the device serial number */
8240
8241 static const v_MACADDR_t default_address =
8242 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008243
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308244 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8245 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008246 {
8247 /* cfg.ini has the default address, invoke autogen logic */
8248
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308249 /* Here, passing Arg2 as 0 because we want to change the
8250 last 3 bytes (means non OUI bytes) of all the interfaces
8251 mac addr.
8252 */
8253 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8254 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008255 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308256 hddLog(VOS_TRACE_LEVEL_ERROR,
8257 "%s: Failed to generate wlan interface mac addr "
8258 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8259 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008260 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008261 }
8262 else
8263#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8264 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008265 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008266 "%s: Invalid MAC address in NV, using MAC from ini file "
8267 MAC_ADDRESS_STR, __func__,
8268 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8269 }
8270 }
8271 {
8272 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308273
8274 /* Set the MAC Address Currently this is used by HAL to
8275 * add self sta. Remove this once self sta is added as
8276 * part of session open.
8277 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008278 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8279 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8280 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308281
Jeff Johnson295189b2012-06-20 16:38:30 -07008282 if (!HAL_STATUS_SUCCESS( halStatus ))
8283 {
8284 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8285 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mihir Shetee1093ba2014-01-21 20:13:32 +05308286 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008287 }
8288 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008289
8290 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8291 Note: Firmware image will be read and downloaded inside vos_start API */
8292 status = vos_start( pHddCtx->pvosContext );
8293 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8294 {
8295 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308296 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008297 }
8298
Leo Chang6cec3e22014-01-21 15:33:49 -08008299#ifdef FEATURE_WLAN_CH_AVOID
8300 /* Plug in avoid channel notification callback
8301 * This should happen before ADD_SELF_STA
8302 * FW will send first IND with ADD_SELF_STA REQ from host */
8303 sme_AddChAvoidCallback(pHddCtx->hHal,
8304 hdd_hostapd_ch_avoid_cb);
8305#endif /* FEATURE_WLAN_CH_AVOID */
8306
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008307 /* Exchange capability info between Host and FW and also get versioning info from FW */
8308 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008309
8310 status = hdd_post_voss_start_config( pHddCtx );
8311 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8312 {
8313 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8314 __func__);
8315 goto err_vosstop;
8316 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008317
8318#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308319 wlan_hdd_cfg80211_update_reg_info( wiphy );
8320
8321 /* registration of wiphy dev with cfg80211 */
8322 if (0 > wlan_hdd_cfg80211_register(wiphy))
8323 {
8324 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8325 goto err_vosstop;
8326 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008327#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008328
Jeff Johnson295189b2012-06-20 16:38:30 -07008329 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8330 {
8331 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8332 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8333 }
8334 else
8335 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008336 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8337 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8338 if (pAdapter != NULL)
8339 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308340 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07008341 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308342 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8343 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8344 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008345
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308346 /* Generate the P2P Device Address. This consists of the device's
8347 * primary MAC address with the locally administered bit set.
8348 */
8349 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008350 }
8351 else
8352 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308353 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8354 if (p2p_dev_addr != NULL)
8355 {
8356 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8357 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8358 }
8359 else
8360 {
8361 hddLog(VOS_TRACE_LEVEL_FATAL,
8362 "%s: Failed to allocate mac_address for p2p_device",
8363 __func__);
8364 goto err_close_adapter;
8365 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008366 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008367
8368 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8369 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8370 if ( NULL == pP2pAdapter )
8371 {
8372 hddLog(VOS_TRACE_LEVEL_FATAL,
8373 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008374 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008375 goto err_close_adapter;
8376 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008377 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008378 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008379
8380 if( pAdapter == NULL )
8381 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008382 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8383 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008384 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008385
Arif Hussain66559122013-11-21 10:11:40 -08008386 if (country_code)
8387 {
8388 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008389 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008390 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8391#ifndef CONFIG_ENABLE_LINUX_REG
8392 hdd_checkandupdate_phymode(pAdapter, country_code);
8393#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08008394 ret = sme_ChangeCountryCode(pHddCtx->hHal,
8395 (void *)(tSmeChangeCountryCallback)
8396 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08008397 country_code,
8398 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308399 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008400 if (eHAL_STATUS_SUCCESS == ret)
8401 {
Arif Hussaincb607082013-12-20 11:57:42 -08008402 ret = wait_for_completion_interruptible_timeout(
8403 &pAdapter->change_country_code,
8404 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8405
8406 if (0 >= ret)
8407 {
8408 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8409 "%s: SME while setting country code timed out", __func__);
8410 }
Arif Hussain66559122013-11-21 10:11:40 -08008411 }
8412 else
8413 {
Arif Hussaincb607082013-12-20 11:57:42 -08008414 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8415 "%s: SME Change Country code from module param fail ret=%d",
8416 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008417 }
8418 }
8419
Jeff Johnson295189b2012-06-20 16:38:30 -07008420#ifdef WLAN_BTAMP_FEATURE
8421 vStatus = WLANBAP_Open(pVosContext);
8422 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8423 {
8424 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8425 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008426 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008427 }
8428
8429 vStatus = BSL_Init(pVosContext);
8430 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8431 {
8432 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8433 "%s: Failed to Init BSL",__func__);
8434 goto err_bap_close;
8435 }
8436 vStatus = WLANBAP_Start(pVosContext);
8437 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8438 {
8439 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8440 "%s: Failed to start TL",__func__);
8441 goto err_bap_close;
8442 }
8443
8444 pConfig = pHddCtx->cfg_ini;
8445 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8446 status = WLANBAP_SetConfig(&btAmpConfig);
8447
8448#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008449
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008450#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8451 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8452 {
8453 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8454 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8455 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8456 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8457 }
8458#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008459#ifdef FEATURE_WLAN_SCAN_PNO
8460 /*SME must send channel update configuration to RIVA*/
8461 sme_UpdateChannelConfig(pHddCtx->hHal);
8462#endif
8463
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308464 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
8465
Jeff Johnson295189b2012-06-20 16:38:30 -07008466 /* Register with platform driver as client for Suspend/Resume */
8467 status = hddRegisterPmOps(pHddCtx);
8468 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8469 {
8470 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8471#ifdef WLAN_BTAMP_FEATURE
8472 goto err_bap_stop;
8473#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008474 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008475#endif //WLAN_BTAMP_FEATURE
8476 }
8477
Yue Ma0d4891e2013-08-06 17:01:45 -07008478 /* Open debugfs interface */
8479 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8480 {
8481 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8482 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008483 }
8484
Jeff Johnson295189b2012-06-20 16:38:30 -07008485 /* Register TM level change handler function to the platform */
8486 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8487 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8488 {
8489 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8490 goto err_unregister_pmops;
8491 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008492
8493 /* register for riva power on lock to platform driver */
8494 if (req_riva_power_on_lock("wlan"))
8495 {
8496 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8497 __func__);
8498 goto err_unregister_pmops;
8499 }
8500
Jeff Johnson295189b2012-06-20 16:38:30 -07008501 // register net device notifier for device change notification
8502 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8503
8504 if(ret < 0)
8505 {
8506 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8507 goto err_free_power_on_lock;
8508 }
8509
8510 //Initialize the nlink service
8511 if(nl_srv_init() != 0)
8512 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308513 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008514 goto err_reg_netdev;
8515 }
8516
Leo Chang4ce1cc52013-10-21 18:27:15 -07008517#ifdef WLAN_KD_READY_NOTIFIER
8518 pHddCtx->kd_nl_init = 1;
8519#endif /* WLAN_KD_READY_NOTIFIER */
8520
Jeff Johnson295189b2012-06-20 16:38:30 -07008521 //Initialize the BTC service
8522 if(btc_activate_service(pHddCtx) != 0)
8523 {
8524 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8525 goto err_nl_srv;
8526 }
8527
8528#ifdef PTT_SOCK_SVC_ENABLE
8529 //Initialize the PTT service
8530 if(ptt_sock_activate_svc(pHddCtx) != 0)
8531 {
8532 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8533 goto err_nl_srv;
8534 }
8535#endif
8536
Jeff Johnson295189b2012-06-20 16:38:30 -07008537 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008538 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008539 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008540 /* Action frame registered in one adapter which will
8541 * applicable to all interfaces
8542 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008543 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008544 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008545
8546 mutex_init(&pHddCtx->sap_lock);
8547
8548 pHddCtx->isLoadUnloadInProgress = FALSE;
8549
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008550#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008551#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8552 /* Initialize the wake lcok */
8553 wake_lock_init(&pHddCtx->rx_wake_lock,
8554 WAKE_LOCK_SUSPEND,
8555 "qcom_rx_wakelock");
8556#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008557 /* Initialize the wake lcok */
8558 wake_lock_init(&pHddCtx->sap_wake_lock,
8559 WAKE_LOCK_SUSPEND,
8560 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008561#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008562
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008563 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8564 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008565
8566 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8567 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308568#ifndef CONFIG_ENABLE_LINUX_REG
8569 /*updating wiphy so that regulatory user hints can be processed*/
8570 if (wiphy)
8571 {
8572 regulatory_hint(wiphy, "00");
8573 }
8574#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008575 // Initialize the restart logic
8576 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308577
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008578 //Register the traffic monitor timer now
8579 if ( pHddCtx->cfg_ini->dynSplitscan)
8580 {
8581 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8582 VOS_TIMER_TYPE_SW,
8583 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8584 (void *)pHddCtx);
8585 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008586 goto success;
8587
8588err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008589#ifdef WLAN_KD_READY_NOTIFIER
8590 nl_srv_exit(pHddCtx->ptt_pid);
8591#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008592 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008593#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008594err_reg_netdev:
8595 unregister_netdevice_notifier(&hdd_netdev_notifier);
8596
8597err_free_power_on_lock:
8598 free_riva_power_on_lock("wlan");
8599
8600err_unregister_pmops:
8601 hddDevTmUnregisterNotifyCallback(pHddCtx);
8602 hddDeregisterPmOps(pHddCtx);
8603
Yue Ma0d4891e2013-08-06 17:01:45 -07008604 hdd_debugfs_exit(pHddCtx);
8605
Jeff Johnson295189b2012-06-20 16:38:30 -07008606#ifdef WLAN_BTAMP_FEATURE
8607err_bap_stop:
8608 WLANBAP_Stop(pVosContext);
8609#endif
8610
8611#ifdef WLAN_BTAMP_FEATURE
8612err_bap_close:
8613 WLANBAP_Close(pVosContext);
8614#endif
8615
Jeff Johnson295189b2012-06-20 16:38:30 -07008616err_close_adapter:
8617 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008618
8619#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308620 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008621#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008622
8623err_vosstop:
8624 vos_stop(pVosContext);
8625
Mihir Shetee1093ba2014-01-21 20:13:32 +05308626err_wiphy_unregister:
8627#ifdef CONFIG_ENABLE_LINUX_REG
8628 wiphy_unregister(wiphy);
8629#endif
8630
Amar Singhala49cbc52013-10-08 18:37:44 -07008631err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008632 status = vos_sched_close( pVosContext );
8633 if (!VOS_IS_STATUS_SUCCESS(status)) {
8634 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8635 "%s: Failed to close VOSS Scheduler", __func__);
8636 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8637 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008638 vos_close(pVosContext );
8639
Amar Singhala49cbc52013-10-08 18:37:44 -07008640#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008641err_vos_nv_close:
8642
8643 vos_nv_close();
8644
Jeff Johnson295189b2012-06-20 16:38:30 -07008645err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008646#endif
8647
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008648 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008649
8650err_wdclose:
8651 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8652 vos_watchdog_close(pVosContext);
8653
Jeff Johnson295189b2012-06-20 16:38:30 -07008654err_config:
8655 kfree(pHddCtx->cfg_ini);
8656 pHddCtx->cfg_ini= NULL;
8657
8658err_free_hdd_context:
8659 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008660 wiphy_free(wiphy) ;
8661 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008662 VOS_BUG(1);
8663
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008664 if (hdd_is_ssr_required())
8665 {
8666 /* WDI timeout had happened during load, so SSR is needed here */
8667 subsystem_restart("wcnss");
8668 msleep(5000);
8669 }
8670 hdd_set_ssr_required (VOS_FALSE);
8671
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008672 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008673
8674success:
8675 EXIT();
8676 return 0;
8677}
8678
8679/**---------------------------------------------------------------------------
8680
Jeff Johnson32d95a32012-09-10 13:15:23 -07008681 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008682
Jeff Johnson32d95a32012-09-10 13:15:23 -07008683 This is the driver entry point - called in different timeline depending
8684 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008685
8686 \param - None
8687
8688 \return - 0 for success, non zero for failure
8689
8690 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008691static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008692{
8693 VOS_STATUS status;
8694 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008695 struct device *dev = NULL;
8696 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008697#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8698 int max_retries = 0;
8699#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008700
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308701#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8702 vos_wconn_trace_init();
8703#endif
8704
Jeff Johnson295189b2012-06-20 16:38:30 -07008705 ENTER();
8706
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008707#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008708 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008709#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008710
8711 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8712 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8713
8714 //Power Up Libra WLAN card first if not already powered up
8715 status = vos_chipPowerUp(NULL,NULL,NULL);
8716 if (!VOS_IS_STATUS_SUCCESS(status))
8717 {
8718 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8719 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308720#ifdef WLAN_OPEN_SOURCE
8721 wake_lock_destroy(&wlan_wake_lock);
8722#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008723 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008724 }
8725
Jeff Johnson295189b2012-06-20 16:38:30 -07008726#ifdef ANI_BUS_TYPE_PCI
8727
8728 dev = wcnss_wlan_get_device();
8729
8730#endif // ANI_BUS_TYPE_PCI
8731
8732#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008733
8734#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8735 /* wait until WCNSS driver downloads NV */
8736 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8737 msleep(1000);
8738 }
8739 if (max_retries >= 5) {
8740 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308741#ifdef WLAN_OPEN_SOURCE
8742 wake_lock_destroy(&wlan_wake_lock);
8743#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008744 return -ENODEV;
8745 }
8746#endif
8747
Jeff Johnson295189b2012-06-20 16:38:30 -07008748 dev = wcnss_wlan_get_device();
8749#endif // ANI_BUS_TYPE_PLATFORM
8750
8751
8752 do {
8753 if (NULL == dev) {
8754 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8755 ret_status = -1;
8756 break;
8757 }
8758
Jeff Johnson295189b2012-06-20 16:38:30 -07008759#ifdef TIMER_MANAGER
8760 vos_timer_manager_init();
8761#endif
8762
8763 /* Preopen VOSS so that it is ready to start at least SAL */
8764 status = vos_preOpen(&pVosContext);
8765
8766 if (!VOS_IS_STATUS_SUCCESS(status))
8767 {
8768 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8769 ret_status = -1;
8770 break;
8771 }
8772
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008773#ifndef MODULE
8774 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8775 */
8776 hdd_set_conparam((v_UINT_t)con_mode);
8777#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008778
8779 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008780 if (hdd_wlan_startup(dev))
8781 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008782 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008783 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008784 vos_preClose( &pVosContext );
8785 ret_status = -1;
8786 break;
8787 }
8788
8789 /* Cancel the vote for XO Core ON
8790 * This is done here for safety purposes in case we re-initialize without turning
8791 * it OFF in any error scenario.
8792 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008793 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008794 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008795 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008796 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8797 {
8798 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008799 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008800 }
8801 } while (0);
8802
8803 if (0 != ret_status)
8804 {
8805 //Assert Deep sleep signal now to put Libra HW in lowest power state
8806 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8807 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8808
8809 //Vote off any PMIC voltage supplies
8810 vos_chipPowerDown(NULL, NULL, NULL);
8811#ifdef TIMER_MANAGER
8812 vos_timer_exit();
8813#endif
8814#ifdef MEMORY_DEBUG
8815 vos_mem_exit();
8816#endif
8817
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008818#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008819 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008820#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008821 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8822 }
8823 else
8824 {
8825 //Send WLAN UP indication to Nlink Service
8826 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8827
8828 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008829 }
8830
8831 EXIT();
8832
8833 return ret_status;
8834}
8835
Jeff Johnson32d95a32012-09-10 13:15:23 -07008836/**---------------------------------------------------------------------------
8837
8838 \brief hdd_module_init() - Init Function
8839
8840 This is the driver entry point (invoked when module is loaded using insmod)
8841
8842 \param - None
8843
8844 \return - 0 for success, non zero for failure
8845
8846 --------------------------------------------------------------------------*/
8847#ifdef MODULE
8848static int __init hdd_module_init ( void)
8849{
8850 return hdd_driver_init();
8851}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008852#else /* #ifdef MODULE */
8853static int __init hdd_module_init ( void)
8854{
8855 /* Driver initialization is delayed to fwpath_changed_handler */
8856 return 0;
8857}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008858#endif /* #ifdef MODULE */
8859
Jeff Johnson295189b2012-06-20 16:38:30 -07008860
8861/**---------------------------------------------------------------------------
8862
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008863 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008864
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008865 This is the driver exit point (invoked when module is unloaded using rmmod
8866 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008867
8868 \param - None
8869
8870 \return - None
8871
8872 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008873static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008874{
8875 hdd_context_t *pHddCtx = NULL;
8876 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008877 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008878
8879 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8880
8881 //Get the global vos context
8882 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8883
8884 if(!pVosContext)
8885 {
8886 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8887 goto done;
8888 }
8889
8890 //Get the HDD context.
8891 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8892
8893 if(!pHddCtx)
8894 {
8895 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8896 }
8897 else
8898 {
Sameer Thalappil14067972014-01-23 14:54:54 -08008899 while (pHddCtx->isLogpInProgress) {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008900 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8901 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008902 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008903
8904 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8905 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8906 "%s:SSR never completed, fatal error", __func__);
8907 VOS_BUG(0);
8908 }
8909 }
8910
Jeff Johnson295189b2012-06-20 16:38:30 -07008911
8912 pHddCtx->isLoadUnloadInProgress = TRUE;
8913 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8914
8915 //Do all the cleanup before deregistering the driver
8916 hdd_wlan_exit(pHddCtx);
8917 }
8918
Jeff Johnson295189b2012-06-20 16:38:30 -07008919 vos_preClose( &pVosContext );
8920
8921#ifdef TIMER_MANAGER
8922 vos_timer_exit();
8923#endif
8924#ifdef MEMORY_DEBUG
8925 vos_mem_exit();
8926#endif
8927
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308928#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8929 vos_wconn_trace_exit();
8930#endif
8931
Jeff Johnson295189b2012-06-20 16:38:30 -07008932done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008933#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008934 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008935#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008936 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8937}
8938
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008939/**---------------------------------------------------------------------------
8940
8941 \brief hdd_module_exit() - Exit function
8942
8943 This is the driver exit point (invoked when module is unloaded using rmmod)
8944
8945 \param - None
8946
8947 \return - None
8948
8949 --------------------------------------------------------------------------*/
8950static void __exit hdd_module_exit(void)
8951{
8952 hdd_driver_exit();
8953}
8954
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008955#ifdef MODULE
8956static int fwpath_changed_handler(const char *kmessage,
8957 struct kernel_param *kp)
8958{
Jeff Johnson76052702013-04-16 13:55:05 -07008959 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008960}
8961
8962static int con_mode_handler(const char *kmessage,
8963 struct kernel_param *kp)
8964{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008965 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008966}
8967#else /* #ifdef MODULE */
8968/**---------------------------------------------------------------------------
8969
Jeff Johnson76052702013-04-16 13:55:05 -07008970 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008971
Jeff Johnson76052702013-04-16 13:55:05 -07008972 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008973 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008974 - invoked when module parameter fwpath is modified from userspace to signal
8975 initializing the WLAN driver or when con_mode is modified from userspace
8976 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008977
8978 \return - 0 for success, non zero for failure
8979
8980 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008981static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008982{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008983 int ret_status;
8984
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008985 if (!wlan_hdd_inited) {
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008986 ret_status = hdd_driver_init();
8987 wlan_hdd_inited = ret_status ? 0 : 1;
8988 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008989 }
8990
8991 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07008992
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008993 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07008994
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008995 ret_status = hdd_driver_init();
8996 wlan_hdd_inited = ret_status ? 0 : 1;
8997 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008998}
8999
Jeff Johnson295189b2012-06-20 16:38:30 -07009000/**---------------------------------------------------------------------------
9001
Jeff Johnson76052702013-04-16 13:55:05 -07009002 \brief fwpath_changed_handler() - Handler Function
9003
9004 Handle changes to the fwpath parameter
9005
9006 \return - 0 for success, non zero for failure
9007
9008 --------------------------------------------------------------------------*/
9009static int fwpath_changed_handler(const char *kmessage,
9010 struct kernel_param *kp)
9011{
9012 int ret;
9013
9014 ret = param_set_copystring(kmessage, kp);
9015 if (0 == ret)
9016 ret = kickstart_driver();
9017 return ret;
9018}
9019
9020/**---------------------------------------------------------------------------
9021
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009022 \brief con_mode_handler() -
9023
9024 Handler function for module param con_mode when it is changed by userspace
9025 Dynamically linked - do nothing
9026 Statically linked - exit and init driver, as in rmmod and insmod
9027
Jeff Johnson76052702013-04-16 13:55:05 -07009028 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009029
Jeff Johnson76052702013-04-16 13:55:05 -07009030 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009031
9032 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009033static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009034{
Jeff Johnson76052702013-04-16 13:55:05 -07009035 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009036
Jeff Johnson76052702013-04-16 13:55:05 -07009037 ret = param_set_int(kmessage, kp);
9038 if (0 == ret)
9039 ret = kickstart_driver();
9040 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009041}
9042#endif /* #ifdef MODULE */
9043
9044/**---------------------------------------------------------------------------
9045
Jeff Johnson295189b2012-06-20 16:38:30 -07009046 \brief hdd_get_conparam() -
9047
9048 This is the driver exit point (invoked when module is unloaded using rmmod)
9049
9050 \param - None
9051
9052 \return - tVOS_CON_MODE
9053
9054 --------------------------------------------------------------------------*/
9055tVOS_CON_MODE hdd_get_conparam ( void )
9056{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009057#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009058 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009059#else
9060 return (tVOS_CON_MODE)curr_con_mode;
9061#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009062}
9063void hdd_set_conparam ( v_UINT_t newParam )
9064{
9065 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009066#ifndef MODULE
9067 curr_con_mode = con_mode;
9068#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009069}
9070/**---------------------------------------------------------------------------
9071
9072 \brief hdd_softap_sta_deauth() - function
9073
9074 This to take counter measure to handle deauth req from HDD
9075
9076 \param - pAdapter - Pointer to the HDD
9077
9078 \param - enable - boolean value
9079
9080 \return - None
9081
9082 --------------------------------------------------------------------------*/
9083
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009084VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009085{
Jeff Johnson295189b2012-06-20 16:38:30 -07009086 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009087 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009088
9089 ENTER();
9090
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009091 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9092 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009093
9094 //Ignore request to deauth bcmc station
9095 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009096 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009097
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009098 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009099
9100 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009101 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009102}
9103
9104/**---------------------------------------------------------------------------
9105
9106 \brief hdd_softap_sta_disassoc() - function
9107
9108 This to take counter measure to handle deauth req from HDD
9109
9110 \param - pAdapter - Pointer to the HDD
9111
9112 \param - enable - boolean value
9113
9114 \return - None
9115
9116 --------------------------------------------------------------------------*/
9117
9118void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9119{
9120 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9121
9122 ENTER();
9123
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309124 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009125
9126 //Ignore request to disassoc bcmc station
9127 if( pDestMacAddress[0] & 0x1 )
9128 return;
9129
9130 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9131}
9132
9133void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9134{
9135 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9136
9137 ENTER();
9138
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309139 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009140
9141 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9142}
9143
Jeff Johnson295189b2012-06-20 16:38:30 -07009144/**---------------------------------------------------------------------------
9145 *
9146 * \brief hdd_get__concurrency_mode() -
9147 *
9148 *
9149 * \param - None
9150 *
9151 * \return - CONCURRENCY MODE
9152 *
9153 * --------------------------------------------------------------------------*/
9154tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9155{
9156 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9157 hdd_context_t *pHddCtx;
9158
9159 if (NULL != pVosContext)
9160 {
9161 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9162 if (NULL != pHddCtx)
9163 {
9164 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9165 }
9166 }
9167
9168 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009169 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009170 return VOS_STA;
9171}
9172
9173/* Decide whether to allow/not the apps power collapse.
9174 * Allow apps power collapse if we are in connected state.
9175 * if not, allow only if we are in IMPS */
9176v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9177{
9178 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009179 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009180 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009181 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9182 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9183 hdd_adapter_t *pAdapter = NULL;
9184 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009185 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009186
Jeff Johnson295189b2012-06-20 16:38:30 -07009187 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9188 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009189
Yathish9f22e662012-12-10 14:21:35 -08009190 concurrent_state = hdd_get_concurrency_mode();
9191
9192#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
9193 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
9194 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
9195 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9196 return TRUE;
9197#endif
9198
Jeff Johnson295189b2012-06-20 16:38:30 -07009199 /*loop through all adapters. TBD fix for Concurrency */
9200 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9201 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9202 {
9203 pAdapter = pAdapterNode->pAdapter;
9204 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9205 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9206 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009207 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07009208 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08009209 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009210 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9211 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009212 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009213 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009214 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9215 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009216 return FALSE;
9217 }
9218 }
9219 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9220 pAdapterNode = pNext;
9221 }
9222 return TRUE;
9223}
9224
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08009225/* Decides whether to send suspend notification to Riva
9226 * if any adapter is in BMPS; then it is required */
9227v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
9228{
9229 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
9230 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9231
9232 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
9233 {
9234 return TRUE;
9235 }
9236 return FALSE;
9237}
9238
Jeff Johnson295189b2012-06-20 16:38:30 -07009239void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9240{
9241 switch(mode)
9242 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009243 case VOS_STA_MODE:
9244 case VOS_P2P_CLIENT_MODE:
9245 case VOS_P2P_GO_MODE:
9246 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07009247 pHddCtx->concurrency_mode |= (1 << mode);
9248 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07009249 break;
9250 default:
9251 break;
9252
9253 }
9254 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9255 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9256}
9257
9258
9259void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9260{
9261 switch(mode)
9262 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009263 case VOS_STA_MODE:
9264 case VOS_P2P_CLIENT_MODE:
9265 case VOS_P2P_GO_MODE:
9266 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009267 pHddCtx->no_of_sessions[mode]--;
9268 if (!(pHddCtx->no_of_sessions[mode]))
9269 pHddCtx->concurrency_mode &= (~(1 << mode));
9270 break;
9271 default:
9272 break;
9273 }
9274 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9275 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9276}
9277
Jeff Johnsone7245742012-09-05 17:12:55 -07009278/**---------------------------------------------------------------------------
9279 *
9280 * \brief wlan_hdd_restart_init
9281 *
9282 * This function initalizes restart timer/flag. An internal function.
9283 *
9284 * \param - pHddCtx
9285 *
9286 * \return - None
9287 *
9288 * --------------------------------------------------------------------------*/
9289
9290static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9291{
9292 /* Initialize */
9293 pHddCtx->hdd_restart_retries = 0;
9294 atomic_set(&pHddCtx->isRestartInProgress, 0);
9295 vos_timer_init(&pHddCtx->hdd_restart_timer,
9296 VOS_TIMER_TYPE_SW,
9297 wlan_hdd_restart_timer_cb,
9298 pHddCtx);
9299}
9300/**---------------------------------------------------------------------------
9301 *
9302 * \brief wlan_hdd_restart_deinit
9303 *
9304 * This function cleans up the resources used. An internal function.
9305 *
9306 * \param - pHddCtx
9307 *
9308 * \return - None
9309 *
9310 * --------------------------------------------------------------------------*/
9311
9312static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9313{
9314
9315 VOS_STATUS vos_status;
9316 /* Block any further calls */
9317 atomic_set(&pHddCtx->isRestartInProgress, 1);
9318 /* Cleanup */
9319 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9320 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309321 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009322 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9323 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309324 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009325
9326}
9327
9328/**---------------------------------------------------------------------------
9329 *
9330 * \brief wlan_hdd_framework_restart
9331 *
9332 * This function uses a cfg80211 API to start a framework initiated WLAN
9333 * driver module unload/load.
9334 *
9335 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9336 *
9337 *
9338 * \param - pHddCtx
9339 *
9340 * \return - VOS_STATUS_SUCCESS: Success
9341 * VOS_STATUS_E_EMPTY: Adapter is Empty
9342 * VOS_STATUS_E_NOMEM: No memory
9343
9344 * --------------------------------------------------------------------------*/
9345
9346static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9347{
9348 VOS_STATUS status = VOS_STATUS_SUCCESS;
9349 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009350 int len = (sizeof (struct ieee80211_mgmt));
9351 struct ieee80211_mgmt *mgmt = NULL;
9352
9353 /* Prepare the DEAUTH managment frame with reason code */
9354 mgmt = kzalloc(len, GFP_KERNEL);
9355 if(mgmt == NULL)
9356 {
9357 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9358 "%s: memory allocation failed (%d bytes)", __func__, len);
9359 return VOS_STATUS_E_NOMEM;
9360 }
9361 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009362
9363 /* Iterate over all adapters/devices */
9364 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9365 do
9366 {
9367 if( (status == VOS_STATUS_SUCCESS) &&
9368 pAdapterNode &&
9369 pAdapterNode->pAdapter)
9370 {
9371 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9372 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9373 pAdapterNode->pAdapter->dev->name,
9374 pAdapterNode->pAdapter->device_mode,
9375 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009376 /*
9377 * CFG80211 event to restart the driver
9378 *
9379 * 'cfg80211_send_unprot_deauth' sends a
9380 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9381 * of SME(Linux Kernel) state machine.
9382 *
9383 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9384 * the driver.
9385 *
9386 */
9387
9388 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009389 }
9390 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9391 pAdapterNode = pNext;
9392 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9393
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009394
9395 /* Free the allocated management frame */
9396 kfree(mgmt);
9397
Jeff Johnsone7245742012-09-05 17:12:55 -07009398 /* Retry until we unload or reach max count */
9399 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9400 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9401
9402 return status;
9403
9404}
9405/**---------------------------------------------------------------------------
9406 *
9407 * \brief wlan_hdd_restart_timer_cb
9408 *
9409 * Restart timer callback. An internal function.
9410 *
9411 * \param - User data:
9412 *
9413 * \return - None
9414 *
9415 * --------------------------------------------------------------------------*/
9416
9417void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9418{
9419 hdd_context_t *pHddCtx = usrDataForCallback;
9420 wlan_hdd_framework_restart(pHddCtx);
9421 return;
9422
9423}
9424
9425
9426/**---------------------------------------------------------------------------
9427 *
9428 * \brief wlan_hdd_restart_driver
9429 *
9430 * This function sends an event to supplicant to restart the WLAN driver.
9431 *
9432 * This function is called from vos_wlanRestart.
9433 *
9434 * \param - pHddCtx
9435 *
9436 * \return - VOS_STATUS_SUCCESS: Success
9437 * VOS_STATUS_E_EMPTY: Adapter is Empty
9438 * VOS_STATUS_E_ALREADY: Request already in progress
9439
9440 * --------------------------------------------------------------------------*/
9441VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9442{
9443 VOS_STATUS status = VOS_STATUS_SUCCESS;
9444
9445 /* A tight check to make sure reentrancy */
9446 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9447 {
9448 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9449 "%s: WLAN restart is already in progress", __func__);
9450
9451 return VOS_STATUS_E_ALREADY;
9452 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009453 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009454#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009455 wcnss_reset_intr();
9456#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009457
Jeff Johnsone7245742012-09-05 17:12:55 -07009458 return status;
9459}
9460
Mihir Shetee1093ba2014-01-21 20:13:32 +05309461/**---------------------------------------------------------------------------
9462 *
9463 * \brief wlan_hdd_init_channels
9464 *
9465 * This function is used to initialize the channel list in CSR
9466 *
9467 * This function is called from hdd_wlan_startup
9468 *
9469 * \param - pHddCtx: HDD context
9470 *
9471 * \return - VOS_STATUS_SUCCESS: Success
9472 * VOS_STATUS_E_FAULT: Failure reported by SME
9473
9474 * --------------------------------------------------------------------------*/
9475static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
9476{
9477 eHalStatus status;
9478
9479 status = sme_InitChannels(pHddCtx->hHal);
9480 if (HAL_STATUS_SUCCESS(status))
9481 {
9482 return VOS_STATUS_SUCCESS;
9483 }
9484 else
9485 {
9486 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
9487 __func__, status);
9488 return VOS_STATUS_E_FAULT;
9489 }
9490}
9491
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009492/*
9493 * API to find if there is any STA or P2P-Client is connected
9494 */
9495VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9496{
9497 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9498}
Jeff Johnsone7245742012-09-05 17:12:55 -07009499
Jeff Johnson295189b2012-06-20 16:38:30 -07009500//Register the module init/exit functions
9501module_init(hdd_module_init);
9502module_exit(hdd_module_exit);
9503
9504MODULE_LICENSE("Dual BSD/GPL");
9505MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9506MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9507
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009508module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9509 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009510
Jeff Johnson76052702013-04-16 13:55:05 -07009511module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009512 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009513
9514module_param(enable_dfs_chan_scan, int,
9515 S_IRUSR | S_IRGRP | S_IROTH);
9516
9517module_param(enable_11d, int,
9518 S_IRUSR | S_IRGRP | S_IROTH);
9519
9520module_param(country_code, charp,
9521 S_IRUSR | S_IRGRP | S_IROTH);