blob: c02531ba1f9657248cc9bc6192d84678ac99af97 [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 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800939 ucRfBand = HDD_SET_BATCH_SCAN_24GHz_BAND_ONLY;
Rajeev79dbe4c2013-10-05 11:03:42 +0530940 }
941 else if (('B' == val) || ('b' == val))
942 {
Rajeev Kumar45e64a72013-11-18 19:48:15 -0800943 ucRfBand = HDD_SET_BATCH_SCAN_5GHz_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,
3425 FL("BTCOEXMODE %d"), *dhcpPhase);
3426
3427 pHddCtx->btCoexModeSet = TRUE;
3428
3429 /* Firmware failing to process DHCP START/STOP indications.
3430 * So, for now commentig below code, once issue is resolved,
3431 * follwing will be uncommented.
3432 */
3433 #if 0
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303434 sme_DHCPStartInd(pHddCtx->hHal, pAdapter->device_mode,
3435 pAdapter->macAddressCurrent.bytes);
c_hpothu9b781ba2013-12-30 20:57:45 +05303436 #endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303437 }
3438 else if ('2' == *dhcpPhase)
3439 {
c_hpothu9b781ba2013-12-30 20:57:45 +05303440 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3441 FL("BTCOEXMODE %d"), *dhcpPhase);
3442
3443 pHddCtx->btCoexModeSet = FALSE;
3444
3445 /* Firmware failing to process DHCP START/STOP indications.
3446 * So, for now commentig below code, once issue is resolved,
3447 * follwing will be uncommented.
3448 */
3449 #if 0
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303450 sme_DHCPStopInd(pHddCtx->hHal, pAdapter->device_mode,
3451 pAdapter->macAddressCurrent.bytes);
c_hpothu9b781ba2013-12-30 20:57:45 +05303452 #endif
Sundaresan Ramachandran76e48e82013-07-15 13:07:17 +05303453 }
3454 }
Jeff Johnsonf54df2c2013-07-24 11:43:39 -07003455 else if (strncmp(command, "SCAN-ACTIVE", 11) == 0)
3456 {
3457 pHddCtx->scan_info.scan_mode = eSIR_ACTIVE_SCAN;
3458 }
3459 else if (strncmp(command, "SCAN-PASSIVE", 12) == 0)
3460 {
3461 pHddCtx->scan_info.scan_mode = eSIR_PASSIVE_SCAN;
3462 }
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303463 else if (strncmp(command, "GETDWELLTIME", 12) == 0)
3464 {
3465 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3466 char extra[32];
3467 tANI_U8 len = 0;
3468
Sameer Thalappilb0a30232013-09-27 15:37:48 -07003469 len = scnprintf(extra, sizeof(extra), "GETDWELLTIME %u\n",
Hanumantha Reddy Pothula212243c2013-08-01 17:28:31 +05303470 (int)pCfg->nActiveMaxChnTime);
3471 if (copy_to_user(priv_data.buf, &extra, len + 1))
3472 {
3473 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3474 "%s: failed to copy data to user buffer", __func__);
3475 ret = -EFAULT;
3476 goto exit;
3477 }
3478 ret = len;
3479 }
3480 else if (strncmp(command, "SETDWELLTIME", 12) == 0)
3481 {
3482 tANI_U8 *value = command;
3483 hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini;
3484 int val = 0, temp;
3485
3486 value = value + 13;
3487 temp = kstrtou32(value, 10, &val);
3488 if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN ||
3489 val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX )
3490 {
3491 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3492 "%s: argument passed for SETDWELLTIME is incorrect", __func__);
3493 ret = -EFAULT;
3494 goto exit;
3495 }
3496 pCfg->nActiveMaxChnTime = val;
3497 }
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07003498 else if ( strncasecmp(command, "MIRACAST", 8) == 0 )
3499 {
3500 tANI_U8 filterType = 0;
3501 tANI_U8 *value;
3502 value = command + 9;
3503
3504 /* Convert the value from ascii to integer */
3505 ret = kstrtou8(value, 10, &filterType);
3506 if (ret < 0)
3507 {
3508 /* If the input value is greater than max value of datatype,
3509 * then also kstrtou8 fails
3510 */
3511 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3512 "%s: kstrtou8 failed range ", __func__);
3513 ret = -EINVAL;
3514 goto exit;
3515 }
3516 if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) ||
3517 (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL))
3518 {
3519 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3520 "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source,"
3521 " 2-Sink ", __func__);
3522 ret = -EINVAL;
3523 goto exit;
3524 }
3525 //Filtertype value should be either 0-Disabled, 1-Source, 2-sink
3526 pHddCtx->drvr_miracast = filterType;
3527 hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx);
3528 }
Leo Chang614d2072013-08-22 14:59:44 -07003529 else if (strncmp(command, "SETMCRATE", 9) == 0)
3530 {
Leo Chang614d2072013-08-22 14:59:44 -07003531 tANI_U8 *value = command;
3532 int targetRate;
Leo Chang1f98cbd2013-10-17 15:03:52 -07003533 tSirRateUpdateInd *rateUpdate;
3534 eHalStatus status;
Leo Chang614d2072013-08-22 14:59:44 -07003535
3536 /* Only valid for SAP mode */
3537 if (WLAN_HDD_SOFTAP != pAdapter->device_mode)
3538 {
3539 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3540 "%s: SAP mode is not running", __func__);
3541 ret = -EFAULT;
3542 goto exit;
3543 }
3544
3545 /* Move pointer to ahead of SETMCRATE<delimiter> */
3546 /* input value is in units of hundred kbps */
3547 value = value + 10;
3548 /* Convert the value from ascii to integer, decimal base */
3549 ret = kstrtouint(value, 10, &targetRate);
3550
Leo Chang1f98cbd2013-10-17 15:03:52 -07003551 rateUpdate = (tSirRateUpdateInd *)vos_mem_malloc(sizeof(tSirRateUpdateInd));
3552 if (NULL == rateUpdate)
Leo Chang614d2072013-08-22 14:59:44 -07003553 {
Leo Chang1f98cbd2013-10-17 15:03:52 -07003554 hddLog(VOS_TRACE_LEVEL_ERROR,
3555 "%s: SETMCRATE indication alloc fail", __func__);
3556 ret = -EFAULT;
3557 goto exit;
3558 }
3559 vos_mem_zero(rateUpdate, sizeof(tSirRateUpdateInd ));
3560
3561 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3562 "MC Target rate %d", targetRate);
3563 /* Ignore unicast */
3564 rateUpdate->ucastDataRate = -1;
3565 rateUpdate->mcastDataRate24GHz = targetRate;
3566 rateUpdate->mcastDataRate5GHz = targetRate;
3567 rateUpdate->mcastDataRate24GHzTxFlag = 0;
3568 rateUpdate->mcastDataRate5GHzTxFlag = 0;
3569 status = sme_SendRateUpdateInd(pHddCtx->hHal, rateUpdate);
3570 if (eHAL_STATUS_SUCCESS != status)
3571 {
3572 hddLog(VOS_TRACE_LEVEL_ERROR,
3573 "%s: SET_MC_RATE failed", __func__);
3574 vos_mem_free(rateUpdate);
3575 ret = -EFAULT;
3576 goto exit;
Leo Chang614d2072013-08-22 14:59:44 -07003577 }
3578 }
Rajeev79dbe4c2013-10-05 11:03:42 +05303579#ifdef FEATURE_WLAN_BATCH_SCAN
Rajeev Kumar8b373292014-01-08 20:36:55 -08003580 else if (strncmp(command, "WLS_BATCHING", 12) == 0)
Rajeev79dbe4c2013-10-05 11:03:42 +05303581 {
Rajeev Kumar8b373292014-01-08 20:36:55 -08003582 ret = hdd_handle_batch_scan_ioctl(pAdapter, &priv_data, command);
Rajeev79dbe4c2013-10-05 11:03:42 +05303583 }
3584#endif
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003585#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
3586 else if (strncmp(command, "SETCCXROAMSCANCHANNELS", 22) == 0)
3587 {
3588 tANI_U8 *value = command;
3589 tANI_U8 ChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0};
3590 tANI_U8 numChannels = 0;
3591 eHalStatus status = eHAL_STATUS_SUCCESS;
3592
3593 status = hdd_parse_channellist(value, ChannelList, &numChannels);
3594 if (eHAL_STATUS_SUCCESS != status)
3595 {
3596 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3597 "%s: Failed to parse channel list information", __func__);
3598 ret = -EINVAL;
3599 goto exit;
3600 }
3601
3602 if (numChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN)
3603 {
3604 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3605 "%s: number of channels (%d) supported exceeded max (%d)", __func__,
3606 numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN);
3607 ret = -EINVAL;
3608 goto exit;
3609 }
3610 status = sme_SetCcxRoamScanChannelList((tHalHandle)(pHddCtx->hHal),
3611 ChannelList,
3612 numChannels);
3613 if (eHAL_STATUS_SUCCESS != status)
3614 {
3615 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3616 "%s: Failed to update channel list information", __func__);
3617 ret = -EINVAL;
3618 goto exit;
3619 }
3620 }
3621 else if (strncmp(command, "GETTSMSTATS", 11) == 0)
3622 {
3623 tANI_U8 *value = command;
3624 char extra[128] = {0};
3625 int len = 0;
3626 tANI_U8 tid = 0;
3627 hdd_station_ctx_t *pHddStaCtx = NULL;
3628 tAniTrafStrmMetrics tsmMetrics;
3629 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3630
3631 /* if not associated, return error */
3632 if (eConnectionState_Associated != pHddStaCtx->conn_info.connState)
3633 {
3634 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:Not associated!",__func__);
3635 ret = -EINVAL;
3636 goto exit;
3637 }
3638
3639 /* Move pointer to ahead of GETTSMSTATS<delimiter> */
3640 value = value + 12;
3641 /* Convert the value from ascii to integer */
3642 ret = kstrtou8(value, 10, &tid);
3643 if (ret < 0)
3644 {
3645 /* If the input value is greater than max value of datatype, then also
3646 kstrtou8 fails */
3647 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3648 "%s: kstrtou8 failed range [%d - %d]", __func__,
3649 TID_MIN_VALUE,
3650 TID_MAX_VALUE);
3651 ret = -EINVAL;
3652 goto exit;
3653 }
3654
3655 if ((tid < TID_MIN_VALUE) || (tid > TID_MAX_VALUE))
3656 {
3657 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3658 "tid value %d is out of range"
3659 " (Min: %d Max: %d)", tid,
3660 TID_MIN_VALUE,
3661 TID_MAX_VALUE);
3662 ret = -EINVAL;
3663 goto exit;
3664 }
3665
3666 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3667 "%s: Received Command to get tsm stats tid = %d", __func__, tid);
3668
3669 if (VOS_STATUS_SUCCESS != hdd_get_tsm_stats(pAdapter, tid, &tsmMetrics))
3670 {
3671 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3672 "%s: failed to get tsm stats", __func__);
3673 ret = -EFAULT;
3674 goto exit;
3675 }
3676
3677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
3678 "UplinkPktQueueDly(%d)\n"
3679 "UplinkPktQueueDlyHist[0](%d)\n"
3680 "UplinkPktQueueDlyHist[1](%d)\n"
3681 "UplinkPktQueueDlyHist[2](%d)\n"
3682 "UplinkPktQueueDlyHist[3](%d)\n"
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303683 "UplinkPktTxDly(%u)\n"
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003684 "UplinkPktLoss(%d)\n"
3685 "UplinkPktCount(%d)\n"
3686 "RoamingCount(%d)\n"
3687 "RoamingDly(%d)", tsmMetrics.UplinkPktQueueDly,
3688 tsmMetrics.UplinkPktQueueDlyHist[0],
3689 tsmMetrics.UplinkPktQueueDlyHist[1],
3690 tsmMetrics.UplinkPktQueueDlyHist[2],
3691 tsmMetrics.UplinkPktQueueDlyHist[3],
3692 tsmMetrics.UplinkPktTxDly, tsmMetrics.UplinkPktLoss,
3693 tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount, tsmMetrics.RoamingDly);
3694
3695 /* Output TSM stats is of the format
3696 GETTSMSTATS [PktQueueDly] [PktQueueDlyHist[0]]:[PktQueueDlyHist[1]] ...[RoamingDly]
3697 eg., GETTSMSTATS 10 1:0:0:161 20 1 17 8 39800 */
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003698 len = scnprintf(extra, sizeof(extra), "%s %d %d:%d:%d:%d %u %d %d %d %d", command,
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003699 tsmMetrics.UplinkPktQueueDly, tsmMetrics.UplinkPktQueueDlyHist[0],
3700 tsmMetrics.UplinkPktQueueDlyHist[1], tsmMetrics.UplinkPktQueueDlyHist[2],
3701 tsmMetrics.UplinkPktQueueDlyHist[3], tsmMetrics.UplinkPktTxDly,
3702 tsmMetrics.UplinkPktLoss, tsmMetrics.UplinkPktCount, tsmMetrics.RoamingCount,
3703 tsmMetrics.RoamingDly);
3704
3705 if (copy_to_user(priv_data.buf, &extra, len + 1))
3706 {
3707 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3708 "%s: failed to copy data to user buffer", __func__);
3709 ret = -EFAULT;
3710 goto exit;
3711 }
3712 }
3713 else if (strncmp(command, "SETCCKMIE", 9) == 0)
3714 {
3715 tANI_U8 *value = command;
3716 tANI_U8 *cckmIe = NULL;
3717 tANI_U8 cckmIeLen = 0;
3718 eHalStatus status = eHAL_STATUS_SUCCESS;
3719
3720 status = hdd_parse_get_cckm_ie(value, &cckmIe, &cckmIeLen);
3721 if (eHAL_STATUS_SUCCESS != status)
3722 {
3723 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3724 "%s: Failed to parse cckm ie data", __func__);
3725 ret = -EINVAL;
3726 goto exit;
3727 }
3728
3729 if (cckmIeLen > DOT11F_IE_RSN_MAX_LEN)
3730 {
3731 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3732 "%s: CCKM Ie input length is more than max[%d]", __func__,
3733 DOT11F_IE_RSN_MAX_LEN);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003734 vos_mem_free(cckmIe);
3735 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003736 ret = -EINVAL;
3737 goto exit;
3738 }
3739 sme_SetCCKMIe((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, cckmIe, cckmIeLen);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08003740 vos_mem_free(cckmIe);
3741 cckmIe = NULL;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003742 }
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003743 else if (strncmp(command, "CCXBEACONREQ", 12) == 0)
3744 {
3745 tANI_U8 *value = command;
3746 tCsrCcxBeaconReq ccxBcnReq;
3747 eHalStatus status = eHAL_STATUS_SUCCESS;
3748 status = hdd_parse_ccx_beacon_req(value, &ccxBcnReq);
3749 if (eHAL_STATUS_SUCCESS != status)
3750 {
3751 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3752 "%s: Failed to parse ccx beacon req", __func__);
3753 ret = -EINVAL;
3754 goto exit;
3755 }
3756
3757 sme_SetCcxBeaconRequest((tHalHandle)(pHddCtx->hHal), pAdapter->sessionId, &ccxBcnReq);
3758 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003759#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
Madan Mohan Koyyalamudif9bdd4e2012-10-30 18:05:03 -07003760 else {
3761 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s",
3762 __func__, command);
3763 }
3764
Jeff Johnson295189b2012-06-20 16:38:30 -07003765 }
3766exit:
3767 if (command)
3768 {
3769 kfree(command);
3770 }
3771 return ret;
3772}
3773
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003774
3775
3776#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003777/**---------------------------------------------------------------------------
3778
3779 \brief hdd_parse_ccx_beacon_req() - Parse ccx beacon request
3780
3781 This function parses the ccx beacon request passed in the format
3782 CCXBEACONREQ<space><Number of fields><space><Measurement token>
3783 <space>Channel 1<space>Scan Mode <space>Meas Duration<space>Channel N
3784 <space>Scan Mode N<space>Meas Duration N
3785 if the Number of bcn req fields (N) does not match with the actual number of fields passed
3786 then take N.
3787 <Meas Token><Channel><Scan Mode> and <Meas Duration> are treated as one pair
3788 For example, CCXBEACONREQ 2 1 1 1 30 2 44 0 40.
3789 This function does not take care of removing duplicate channels from the list
3790
3791 \param - pValue Pointer to data
3792 \param - pCcxBcnReq output pointer to store parsed ie information
3793
3794 \return - 0 for success non-zero for failure
3795
3796 --------------------------------------------------------------------------*/
3797static VOS_STATUS hdd_parse_ccx_beacon_req(tANI_U8 *pValue,
3798 tCsrCcxBeaconReq *pCcxBcnReq)
3799{
3800 tANI_U8 *inPtr = pValue;
3801 int tempInt = 0;
3802 int j = 0, i = 0, v = 0;
3803 char buf[32];
3804
3805 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
3806 /*no argument after the command*/
3807 if (NULL == inPtr)
3808 {
3809 return -EINVAL;
3810 }
3811 /*no space after the command*/
3812 else if (SPACE_ASCII_VALUE != *inPtr)
3813 {
3814 return -EINVAL;
3815 }
3816
3817 /*removing empty spaces*/
3818 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3819
3820 /*no argument followed by spaces*/
3821 if ('\0' == *inPtr) return -EINVAL;
3822
3823 /*getting the first argument ie measurement token*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003824 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003825 if (1 != v) return -EINVAL;
3826
3827 v = kstrtos32(buf, 10, &tempInt);
3828 if ( v < 0) return -EINVAL;
3829
3830 pCcxBcnReq->numBcnReqIe = tempInt;
3831
3832 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
3833 "Number of Bcn Req Ie fields(%d)", pCcxBcnReq->numBcnReqIe);
3834
3835 for (j = 0; j < (pCcxBcnReq->numBcnReqIe); j++)
3836 {
3837 for (i = 0; i < 4; i++)
3838 {
3839 /*inPtr pointing to the beginning of first space after number of ie fields*/
3840 inPtr = strpbrk( inPtr, " " );
3841 /*no ie data after the number of ie fields argument*/
3842 if (NULL == inPtr) return -EINVAL;
3843
3844 /*removing empty space*/
3845 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
3846
3847 /*no ie data after the number of ie fields argument and spaces*/
3848 if ( '\0' == *inPtr ) return -EINVAL;
3849
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08003850 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003851 if (1 != v) return -EINVAL;
3852
3853 v = kstrtos32(buf, 10, &tempInt);
3854 if (v < 0) return -EINVAL;
3855
3856 switch (i)
3857 {
3858 case 0: /* Measurement token */
3859 if (tempInt <= 0)
3860 {
3861 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3862 "Invalid Measurement Token(%d)", tempInt);
3863 return -EINVAL;
3864 }
3865 pCcxBcnReq->bcnReq[j].measurementToken = tempInt;
3866 break;
3867
3868 case 1: /* Channel number */
3869 if ((tempInt <= 0) ||
3870 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
3871 {
3872 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3873 "Invalid Channel Number(%d)", tempInt);
3874 return -EINVAL;
3875 }
3876 pCcxBcnReq->bcnReq[j].channel = tempInt;
3877 break;
3878
3879 case 2: /* Scan mode */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003880 if ((tempInt < eSIR_PASSIVE_SCAN) || (tempInt > eSIR_BEACON_TABLE))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003881 {
3882 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3883 "Invalid Scan Mode(%d) Expected{0|1|2}", tempInt);
3884 return -EINVAL;
3885 }
3886 pCcxBcnReq->bcnReq[j].scanMode= tempInt;
3887 break;
3888
3889 case 3: /* Measurement duration */
Varun Reddy Yeturu0b18d5a2013-12-04 11:42:23 -08003890 if (((tempInt <= 0) && (pCcxBcnReq->bcnReq[j].scanMode != eSIR_BEACON_TABLE)) ||
3891 ((tempInt < 0) && (pCcxBcnReq->bcnReq[j].scanMode == eSIR_BEACON_TABLE)))
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003892 {
3893 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
3894 "Invalid Measurement Duration(%d)", tempInt);
3895 return -EINVAL;
3896 }
3897 pCcxBcnReq->bcnReq[j].measurementDuration = tempInt;
3898 break;
3899 }
3900 }
3901 }
3902
3903 for (j = 0; j < pCcxBcnReq->numBcnReqIe; j++)
3904 {
3905 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Arun Kumar Khandavallie8768212014-02-17 16:43:34 +05303906 "Index(%d) Measurement Token(%u)Channel(%u) Scan Mode(%u) Measurement Duration(%u)\n",
Srinivas Girigowda91ccbe82013-11-10 16:37:38 -08003907 j,
3908 pCcxBcnReq->bcnReq[j].measurementToken,
3909 pCcxBcnReq->bcnReq[j].channel,
3910 pCcxBcnReq->bcnReq[j].scanMode,
3911 pCcxBcnReq->bcnReq[j].measurementDuration);
3912 }
3913
3914 return VOS_STATUS_SUCCESS;
3915}
3916
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003917static void hdd_GetTsmStatsCB( tAniTrafStrmMetrics tsmMetrics, const tANI_U32 staId, void *pContext )
3918{
3919 struct statsContext *pStatsContext = NULL;
3920 hdd_adapter_t *pAdapter = NULL;
3921
3922 if (NULL == pContext)
3923 {
3924 hddLog(VOS_TRACE_LEVEL_ERROR,
3925 "%s: Bad param, pContext [%p]",
3926 __func__, pContext);
3927 return;
3928 }
3929
Jeff Johnson72a40512013-12-19 10:14:15 -08003930 /* there is a race condition that exists between this callback
3931 function and the caller since the caller could time out either
3932 before or while this code is executing. we use a spinlock to
3933 serialize these actions */
3934 spin_lock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003935
3936 pStatsContext = pContext;
3937 pAdapter = pStatsContext->pAdapter;
3938 if ((NULL == pAdapter) || (STATS_CONTEXT_MAGIC != pStatsContext->magic))
3939 {
3940 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08003941 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003942 hddLog(VOS_TRACE_LEVEL_WARN,
3943 "%s: Invalid context, pAdapter [%p] magic [%08x]",
3944 __func__, pAdapter, pStatsContext->magic);
3945 return;
3946 }
3947
Jeff Johnson72a40512013-12-19 10:14:15 -08003948 /* context is valid so caller is still waiting */
3949
3950 /* paranoia: invalidate the magic */
3951 pStatsContext->magic = 0;
3952
3953 /* copy over the tsm stats */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003954 pAdapter->tsmStats.UplinkPktQueueDly = tsmMetrics.UplinkPktQueueDly;
3955 vos_mem_copy(pAdapter->tsmStats.UplinkPktQueueDlyHist,
3956 tsmMetrics.UplinkPktQueueDlyHist,
3957 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
3958 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
3959 pAdapter->tsmStats.UplinkPktTxDly = tsmMetrics.UplinkPktTxDly;
3960 pAdapter->tsmStats.UplinkPktLoss = tsmMetrics.UplinkPktLoss;
3961 pAdapter->tsmStats.UplinkPktCount = tsmMetrics.UplinkPktCount;
3962 pAdapter->tsmStats.RoamingCount = tsmMetrics.RoamingCount;
3963 pAdapter->tsmStats.RoamingDly = tsmMetrics.RoamingDly;
3964
Jeff Johnson72a40512013-12-19 10:14:15 -08003965 /* notify the caller */
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003966 complete(&pStatsContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08003967
3968 /* serialization is complete */
3969 spin_unlock(&hdd_context_lock);
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003970}
3971
3972
3973
3974static VOS_STATUS hdd_get_tsm_stats(hdd_adapter_t *pAdapter, const tANI_U8 tid,
3975 tAniTrafStrmMetrics* pTsmMetrics)
3976{
3977 hdd_station_ctx_t *pHddStaCtx = NULL;
3978 eHalStatus hstatus;
Jeff Johnson72a40512013-12-19 10:14:15 -08003979 VOS_STATUS vstatus = VOS_STATUS_SUCCESS;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07003980 long lrc;
3981 struct statsContext context;
3982 hdd_context_t *pHddCtx = NULL;
3983
3984 if (NULL == pAdapter)
3985 {
3986 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: pAdapter is NULL", __func__);
3987 return VOS_STATUS_E_FAULT;
3988 }
3989
3990 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
3991 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
3992
3993 /* we are connected prepare our callback context */
3994 init_completion(&context.completion);
3995 context.pAdapter = pAdapter;
3996 context.magic = STATS_CONTEXT_MAGIC;
3997
3998 /* query tsm stats */
3999 hstatus = sme_GetTsmStats(pHddCtx->hHal, hdd_GetTsmStatsCB,
4000 pHddStaCtx->conn_info.staId[ 0 ],
4001 pHddStaCtx->conn_info.bssId,
4002 &context, pHddCtx->pvosContext, tid);
4003
4004 if (eHAL_STATUS_SUCCESS != hstatus)
4005 {
Jeff Johnson72a40512013-12-19 10:14:15 -08004006 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve statistics",
4007 __func__);
4008 vstatus = VOS_STATUS_E_FAULT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004009 }
4010 else
4011 {
4012 /* request was sent -- wait for the response */
4013 lrc = wait_for_completion_interruptible_timeout(&context.completion,
4014 msecs_to_jiffies(WLAN_WAIT_TIME_STATS));
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004015 if (lrc <= 0)
4016 {
4017 hddLog(VOS_TRACE_LEVEL_ERROR,
4018 "%s: SME %s while retrieving statistics",
4019 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson72a40512013-12-19 10:14:15 -08004020 vstatus = VOS_STATUS_E_TIMEOUT;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004021 }
4022 }
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004023
Jeff Johnson72a40512013-12-19 10:14:15 -08004024 /* either we never sent a request, we sent a request and received a
4025 response or we sent a request and timed out. if we never sent a
4026 request or if we sent a request and got a response, we want to
4027 clear the magic out of paranoia. if we timed out there is a
4028 race condition such that the callback function could be
4029 executing at the same time we are. of primary concern is if the
4030 callback function had already verified the "magic" but had not
4031 yet set the completion variable when a timeout occurred. we
4032 serialize these activities by invalidating the magic while
4033 holding a shared spinlock which will cause us to block if the
4034 callback is currently executing */
4035 spin_lock(&hdd_context_lock);
4036 context.magic = 0;
4037 spin_unlock(&hdd_context_lock);
4038
4039 if (VOS_STATUS_SUCCESS == vstatus)
4040 {
4041 pTsmMetrics->UplinkPktQueueDly = pAdapter->tsmStats.UplinkPktQueueDly;
4042 vos_mem_copy(pTsmMetrics->UplinkPktQueueDlyHist,
4043 pAdapter->tsmStats.UplinkPktQueueDlyHist,
4044 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist)/
4045 sizeof(pAdapter->tsmStats.UplinkPktQueueDlyHist[0]));
4046 pTsmMetrics->UplinkPktTxDly = pAdapter->tsmStats.UplinkPktTxDly;
4047 pTsmMetrics->UplinkPktLoss = pAdapter->tsmStats.UplinkPktLoss;
4048 pTsmMetrics->UplinkPktCount = pAdapter->tsmStats.UplinkPktCount;
4049 pTsmMetrics->RoamingCount = pAdapter->tsmStats.RoamingCount;
4050 pTsmMetrics->RoamingDly = pAdapter->tsmStats.RoamingDly;
4051 }
4052 return vstatus;
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004053}
4054#endif /*FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4055
Srinivas Girigowdade697412013-02-14 16:31:48 -08004056#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR)
4057void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand)
4058{
4059 eCsrBand band = -1;
4060 sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band);
4061 switch (band)
4062 {
4063 case eCSR_BAND_ALL:
4064 *pBand = WLAN_HDD_UI_BAND_AUTO;
4065 break;
4066
4067 case eCSR_BAND_24:
4068 *pBand = WLAN_HDD_UI_BAND_2_4_GHZ;
4069 break;
4070
4071 case eCSR_BAND_5G:
4072 *pBand = WLAN_HDD_UI_BAND_5_GHZ;
4073 break;
4074
4075 default:
4076 hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band);
4077 *pBand = -1;
4078 break;
4079 }
4080}
4081
4082/**---------------------------------------------------------------------------
4083
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004084 \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data
4085
4086 This function parses the send action frame data passed in the format
4087 SENDACTIONFRAME<space><bssid><space><channel><space><dwelltime><space><data>
4088
Srinivas Girigowda56076852013-08-20 14:00:50 -07004089 \param - pValue Pointer to input data
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004090 \param - pTargetApBssid Pointer to target Ap bssid
4091 \param - pChannel Pointer to the Target AP channel
4092 \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame
4093 \param - pBuf Pointer to data
4094 \param - pBufLen Pointer to data length
4095
4096 \return - 0 for success non-zero for failure
4097
4098 --------------------------------------------------------------------------*/
4099VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel,
4100 tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen)
4101{
4102 tANI_U8 *inPtr = pValue;
4103 tANI_U8 *dataEnd;
4104 int tempInt;
4105 int j = 0;
4106 int i = 0;
4107 int v = 0;
4108 tANI_U8 tempBuf[32];
4109 tANI_U8 tempByte = 0;
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004110 /* 12 hexa decimal digits, 5 ':' and '\0' */
4111 tANI_U8 macAddress[18];
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004112
4113 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4114 /*no argument after the command*/
4115 if (NULL == inPtr)
4116 {
4117 return -EINVAL;
4118 }
4119
4120 /*no space after the command*/
4121 else if (SPACE_ASCII_VALUE != *inPtr)
4122 {
4123 return -EINVAL;
4124 }
4125
4126 /*removing empty spaces*/
4127 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4128
4129 /*no argument followed by spaces*/
4130 if ('\0' == *inPtr)
4131 {
4132 return -EINVAL;
4133 }
4134
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004135 v = sscanf(inPtr, "%17s", macAddress);
4136 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004137 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004138 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4139 "Invalid MAC address or All hex inputs are not read (%d)", v);
4140 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004141 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004142
4143 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4144 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4145 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4146 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4147 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4148 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004149
4150 /* point to the next argument */
4151 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4152 /*no argument after the command*/
4153 if (NULL == inPtr) return -EINVAL;
4154
4155 /*removing empty spaces*/
4156 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4157
4158 /*no argument followed by spaces*/
4159 if ('\0' == *inPtr)
4160 {
4161 return -EINVAL;
4162 }
4163
4164 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004165 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004166 if (1 != v) return -EINVAL;
4167
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004168 v = kstrtos32(tempBuf, 10, &tempInt);
Agarwal Ashishc0126762014-02-17 19:30:26 +05304169 if ( v < 0 || tempInt < 0 || tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX )
Kiet Lambe150c22013-11-21 16:30:32 +05304170 return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004171
4172 *pChannel = tempInt;
4173
4174 /* point to the next argument */
4175 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4176 /*no argument after the command*/
4177 if (NULL == inPtr) return -EINVAL;
4178 /*removing empty spaces*/
4179 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4180
4181 /*no argument followed by spaces*/
4182 if ('\0' == *inPtr)
4183 {
4184 return -EINVAL;
4185 }
4186
4187 /*getting the next argument ie the dwell time */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004188 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004189 if (1 != v) return -EINVAL;
4190
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004191 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda5a6e0672014-01-09 14:42:57 -08004192 if ( v < 0 || tempInt < 0) return -EINVAL;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004193
4194 *pDwellTime = tempInt;
4195
4196 /* point to the next argument */
4197 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4198 /*no argument after the command*/
4199 if (NULL == inPtr) return -EINVAL;
4200 /*removing empty spaces*/
4201 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4202
4203 /*no argument followed by spaces*/
4204 if ('\0' == *inPtr)
4205 {
4206 return -EINVAL;
4207 }
4208
4209 /* find the length of data */
4210 dataEnd = inPtr;
4211 while(('\0' != *dataEnd) )
4212 {
4213 dataEnd++;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004214 }
Kiet Lambe150c22013-11-21 16:30:32 +05304215 *pBufLen = dataEnd - inPtr ;
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004216 if ( *pBufLen <= 0) return -EINVAL;
4217
Srinivas Girigowdab5ae85d2013-06-03 10:51:45 -07004218 /* Allocate the number of bytes based on the number of input characters
4219 whether it is even or odd.
4220 if the number of input characters are even, then we need N/2 byte.
4221 if the number of input characters are odd, then we need do (N+1)/2 to
4222 compensate rounding off.
4223 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4224 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4225 *pBuf = vos_mem_malloc((*pBufLen + 1)/2);
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004226 if (NULL == *pBuf)
4227 {
4228 hddLog(VOS_TRACE_LEVEL_FATAL,
4229 "%s: vos_mem_alloc failed ", __func__);
4230 return -EINVAL;
4231 }
4232
4233 /* the buffer received from the upper layer is character buffer,
4234 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4235 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4236 and f0 in 3rd location */
4237 for (i = 0, j = 0; j < *pBufLen; j += 2)
4238 {
Kiet Lambe150c22013-11-21 16:30:32 +05304239 if( j+1 == *pBufLen)
4240 {
4241 tempByte = hdd_parse_hex(inPtr[j]);
4242 }
4243 else
4244 {
4245 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4246 }
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004247 (*pBuf)[i++] = tempByte;
4248 }
4249 *pBufLen = i;
4250 return VOS_STATUS_SUCCESS;
4251}
4252
Srinivas Girigowda100eb322013-03-15 16:48:20 -07004253/**---------------------------------------------------------------------------
4254
Srinivas Girigowdade697412013-02-14 16:31:48 -08004255 \brief hdd_parse_channellist() - HDD Parse channel list
4256
4257 This function parses the channel list passed in the format
4258 SETROAMSCANCHANNELS<space><Number of channels><space>Channel 1<space>Channel 2<space>Channel N
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004259 if the Number of channels (N) does not match with the actual number of channels passed
4260 then take the minimum of N and count of (Ch1, Ch2, ...Ch M)
4261 For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken.
4262 If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48.
4263 This function does not take care of removing duplicate channels from the list
Srinivas Girigowdade697412013-02-14 16:31:48 -08004264
4265 \param - pValue Pointer to input channel list
4266 \param - ChannelList Pointer to local output array to record channel list
4267 \param - pNumChannels Pointer to number of roam scan channels
4268
4269 \return - 0 for success non-zero for failure
4270
4271 --------------------------------------------------------------------------*/
4272VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels)
4273{
4274 tANI_U8 *inPtr = pValue;
4275 int tempInt;
4276 int j = 0;
4277 int v = 0;
4278 char buf[32];
4279
4280 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4281 /*no argument after the command*/
4282 if (NULL == inPtr)
4283 {
4284 return -EINVAL;
4285 }
4286
4287 /*no space after the command*/
4288 else if (SPACE_ASCII_VALUE != *inPtr)
4289 {
4290 return -EINVAL;
4291 }
4292
4293 /*removing empty spaces*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004294 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004295
4296 /*no argument followed by spaces*/
4297 if ('\0' == *inPtr)
4298 {
4299 return -EINVAL;
4300 }
4301
4302 /*getting the first argument ie the number of channels*/
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004303 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004304 if (1 != v) return -EINVAL;
4305
Srinivas Girigowdade697412013-02-14 16:31:48 -08004306 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004307 if ((v < 0) ||
4308 (tempInt <= 0) ||
4309 (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN))
4310 {
4311 return -EINVAL;
4312 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004313
4314 *pNumChannels = tempInt;
4315
4316 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4317 "Number of channels are: %d", *pNumChannels);
4318
4319 for (j = 0; j < (*pNumChannels); j++)
4320 {
4321 /*inPtr pointing to the beginning of first space after number of channels*/
4322 inPtr = strpbrk( inPtr, " " );
4323 /*no channel list after the number of channels argument*/
4324 if (NULL == inPtr)
4325 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004326 if (0 != j)
4327 {
4328 *pNumChannels = j;
4329 return VOS_STATUS_SUCCESS;
4330 }
4331 else
4332 {
4333 return -EINVAL;
4334 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004335 }
4336
4337 /*removing empty space*/
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004338 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++;
Srinivas Girigowdade697412013-02-14 16:31:48 -08004339
4340 /*no channel list after the number of channels argument and spaces*/
4341 if ( '\0' == *inPtr )
4342 {
Srinivas Girigowdacf9a9b42013-03-21 11:55:24 -07004343 if (0 != j)
4344 {
4345 *pNumChannels = j;
4346 return VOS_STATUS_SUCCESS;
4347 }
4348 else
4349 {
4350 return -EINVAL;
4351 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004352 }
4353
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004354 v = sscanf(inPtr, "%31s ", buf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004355 if (1 != v) return -EINVAL;
4356
Srinivas Girigowdade697412013-02-14 16:31:48 -08004357 v = kstrtos32(buf, 10, &tempInt);
Jeff Johnsona1f9afb2013-04-03 09:13:31 -07004358 if ((v < 0) ||
4359 (tempInt <= 0) ||
4360 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4361 {
4362 return -EINVAL;
4363 }
Srinivas Girigowdade697412013-02-14 16:31:48 -08004364 pChannelList[j] = tempInt;
4365
4366 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH,
4367 "Channel %d added to preferred channel list",
4368 pChannelList[j] );
4369 }
4370
Srinivas Girigowdade697412013-02-14 16:31:48 -08004371 return VOS_STATUS_SUCCESS;
4372}
4373
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004374
4375/**---------------------------------------------------------------------------
4376
4377 \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data
4378
4379 This function parses the reasoc command data passed in the format
4380 REASSOC<space><bssid><space><channel>
4381
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004382 \param - pValue Pointer to input data (its a NUL terminated string)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004383 \param - pTargetApBssid Pointer to target Ap bssid
4384 \param - pChannel Pointer to the Target AP channel
4385
4386 \return - 0 for success non-zero for failure
4387
4388 --------------------------------------------------------------------------*/
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004389VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue,
4390 tANI_U8 *pTargetApBssid, tANI_U8 *pChannel)
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004391{
4392 tANI_U8 *inPtr = pValue;
4393 int tempInt;
4394 int v = 0;
4395 tANI_U8 tempBuf[32];
Kiet Lamaa8e15a2014-02-11 23:30:06 -08004396 /* 12 hexa decimal digits, 5 ':' and '\0' */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004397 tANI_U8 macAddress[18];
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004398
4399 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4400 /*no argument after the command*/
4401 if (NULL == inPtr)
4402 {
4403 return -EINVAL;
4404 }
4405
4406 /*no space after the command*/
4407 else if (SPACE_ASCII_VALUE != *inPtr)
4408 {
4409 return -EINVAL;
4410 }
4411
4412 /*removing empty spaces*/
4413 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4414
4415 /*no argument followed by spaces*/
4416 if ('\0' == *inPtr)
4417 {
4418 return -EINVAL;
4419 }
4420
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004421 v = sscanf(inPtr, "%17s", macAddress);
4422 if (!((1 == v) && hdd_is_valid_mac_address(macAddress)))
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004423 {
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004424 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
4425 "Invalid MAC address or All hex inputs are not read (%d)", v);
4426 return -EINVAL;
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004427 }
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004428
4429 pTargetApBssid[0] = hdd_parse_hex(macAddress[0]) << 4 | hdd_parse_hex(macAddress[1]);
4430 pTargetApBssid[1] = hdd_parse_hex(macAddress[3]) << 4 | hdd_parse_hex(macAddress[4]);
4431 pTargetApBssid[2] = hdd_parse_hex(macAddress[6]) << 4 | hdd_parse_hex(macAddress[7]);
4432 pTargetApBssid[3] = hdd_parse_hex(macAddress[9]) << 4 | hdd_parse_hex(macAddress[10]);
4433 pTargetApBssid[4] = hdd_parse_hex(macAddress[12]) << 4 | hdd_parse_hex(macAddress[13]);
4434 pTargetApBssid[5] = hdd_parse_hex(macAddress[15]) << 4 | hdd_parse_hex(macAddress[16]);
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004435
4436 /* point to the next argument */
4437 inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE);
4438 /*no argument after the command*/
4439 if (NULL == inPtr) return -EINVAL;
4440
4441 /*removing empty spaces*/
4442 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4443
4444 /*no argument followed by spaces*/
4445 if ('\0' == *inPtr)
4446 {
4447 return -EINVAL;
4448 }
4449
4450 /*getting the next argument ie the channel number */
Srinivas Girigowda4081bb12014-01-06 17:12:58 -08004451 v = sscanf(inPtr, "%31s ", tempBuf);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004452 if (1 != v) return -EINVAL;
4453
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004454 v = kstrtos32(tempBuf, 10, &tempInt);
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004455 if ((v < 0) ||
4456 (tempInt <= 0) ||
4457 (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX))
4458 {
4459 return -EINVAL;
4460 }
Varun Reddy Yeturu920df212013-05-22 08:07:23 -07004461
4462 *pChannel = tempInt;
4463 return VOS_STATUS_SUCCESS;
4464}
4465
4466#endif
4467
Srinivas Girigowda5cecb202013-10-08 09:13:25 -07004468#if defined(FEATURE_WLAN_CCX) && defined(FEATURE_WLAN_CCX_UPLOAD)
4469/**---------------------------------------------------------------------------
4470
4471 \brief hdd_parse_get_cckm_ie() - HDD Parse and fetch the CCKM IE
4472
4473 This function parses the SETCCKM IE command
4474 SETCCKMIE<space><ie data>
4475
4476 \param - pValue Pointer to input data
4477 \param - pCckmIe Pointer to output cckm Ie
4478 \param - pCckmIeLen Pointer to output cckm ie length
4479
4480 \return - 0 for success non-zero for failure
4481
4482 --------------------------------------------------------------------------*/
4483VOS_STATUS hdd_parse_get_cckm_ie(tANI_U8 *pValue, tANI_U8 **pCckmIe,
4484 tANI_U8 *pCckmIeLen)
4485{
4486 tANI_U8 *inPtr = pValue;
4487 tANI_U8 *dataEnd;
4488 int j = 0;
4489 int i = 0;
4490 tANI_U8 tempByte = 0;
4491
4492 inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE);
4493 /*no argument after the command*/
4494 if (NULL == inPtr)
4495 {
4496 return -EINVAL;
4497 }
4498
4499 /*no space after the command*/
4500 else if (SPACE_ASCII_VALUE != *inPtr)
4501 {
4502 return -EINVAL;
4503 }
4504
4505 /*removing empty spaces*/
4506 while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++;
4507
4508 /*no argument followed by spaces*/
4509 if ('\0' == *inPtr)
4510 {
4511 return -EINVAL;
4512 }
4513
4514 /* find the length of data */
4515 dataEnd = inPtr;
4516 while(('\0' != *dataEnd) )
4517 {
4518 dataEnd++;
4519 ++(*pCckmIeLen);
4520 }
4521 if ( *pCckmIeLen <= 0) return -EINVAL;
4522
4523 /* Allocate the number of bytes based on the number of input characters
4524 whether it is even or odd.
4525 if the number of input characters are even, then we need N/2 byte.
4526 if the number of input characters are odd, then we need do (N+1)/2 to
4527 compensate rounding off.
4528 For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough.
4529 If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */
4530 *pCckmIe = vos_mem_malloc((*pCckmIeLen + 1)/2);
4531 if (NULL == *pCckmIe)
4532 {
4533 hddLog(VOS_TRACE_LEVEL_FATAL,
4534 "%s: vos_mem_alloc failed ", __func__);
4535 return -EINVAL;
4536 }
4537 vos_mem_zero(*pCckmIe, (*pCckmIeLen + 1)/2);
4538 /* the buffer received from the upper layer is character buffer,
4539 we need to prepare the buffer taking 2 characters in to a U8 hex decimal number
4540 for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st
4541 and f0 in 3rd location */
4542 for (i = 0, j = 0; j < *pCckmIeLen; j += 2)
4543 {
4544 tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1]));
4545 (*pCckmIe)[i++] = tempByte;
4546 }
4547 *pCckmIeLen = i;
4548
4549 return VOS_STATUS_SUCCESS;
4550}
4551#endif /* FEATURE_WLAN_CCX && FEATURE_WLAN_CCX_UPLOAD */
4552
Jeff Johnson295189b2012-06-20 16:38:30 -07004553/**---------------------------------------------------------------------------
4554
Srinivas Girigowda0c69aee2013-10-09 17:21:01 -07004555 \brief hdd_is_valid_mac_address() - Validate MAC address
4556
4557 This function validates whether the given MAC address is valid or not
4558 Expected MAC address is of the format XX:XX:XX:XX:XX:XX
4559 where X is the hexa decimal digit character and separated by ':'
4560 This algorithm works even if MAC address is not separated by ':'
4561
4562 This code checks given input string mac contains exactly 12 hexadecimal digits.
4563 and a separator colon : appears in the input string only after
4564 an even number of hex digits.
4565
4566 \param - pMacAddr pointer to the input MAC address
4567 \return - 1 for valid and 0 for invalid
4568
4569 --------------------------------------------------------------------------*/
4570
4571v_BOOL_t hdd_is_valid_mac_address(const tANI_U8 *pMacAddr)
4572{
4573 int xdigit = 0;
4574 int separator = 0;
4575 while (*pMacAddr)
4576 {
4577 if (isxdigit(*pMacAddr))
4578 {
4579 xdigit++;
4580 }
4581 else if (':' == *pMacAddr)
4582 {
4583 if (0 == xdigit || ((xdigit / 2) - 1) != separator)
4584 break;
4585
4586 ++separator;
4587 }
4588 else
4589 {
4590 separator = -1;
4591 /* Invalid MAC found */
4592 return 0;
4593 }
4594 ++pMacAddr;
4595 }
4596 return (xdigit == 12 && (separator == 5 || separator == 0));
4597}
4598
4599/**---------------------------------------------------------------------------
4600
Jeff Johnson295189b2012-06-20 16:38:30 -07004601 \brief hdd_open() - HDD Open function
4602
4603 This is called in response to ifconfig up
4604
4605 \param - dev Pointer to net_device structure
4606
4607 \return - 0 for success non-zero for failure
4608
4609 --------------------------------------------------------------------------*/
4610int hdd_open (struct net_device *dev)
4611{
4612 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4613 hdd_context_t *pHddCtx;
4614 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4615 VOS_STATUS status;
4616 v_BOOL_t in_standby = TRUE;
4617
4618 if (NULL == pAdapter)
4619 {
4620 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304621 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004622 return -ENODEV;
4623 }
4624
4625 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4626 if (NULL == pHddCtx)
4627 {
4628 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004629 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004630 return -ENODEV;
4631 }
4632
4633 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4634 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4635 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004636 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4637 {
4638 hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby",
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304639 __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004640 in_standby = FALSE;
4641 break;
4642 }
4643 else
4644 {
4645 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4646 pAdapterNode = pNext;
4647 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004648 }
4649
4650 if (TRUE == in_standby)
4651 {
4652 if (VOS_STATUS_SUCCESS != wlan_hdd_exit_lowpower(pHddCtx, pAdapter))
4653 {
4654 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to bring "
4655 "wlan out of power save", __func__);
4656 return -EINVAL;
4657 }
4658 }
4659
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004660 set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004661 if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
4662 {
4663 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004664 "%s: Enabling Tx Queues", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004665 /* Enable TX queues only when we are connected */
4666 netif_tx_start_all_queues(dev);
4667 }
4668
4669 return 0;
4670}
4671
4672int hdd_mon_open (struct net_device *dev)
4673{
4674 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4675
4676 if(pAdapter == NULL) {
4677 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004678 "%s: HDD adapter context is Null", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08004679 return -EINVAL;
Jeff Johnson295189b2012-06-20 16:38:30 -07004680 }
4681
4682 netif_start_queue(dev);
4683
4684 return 0;
4685}
4686/**---------------------------------------------------------------------------
4687
4688 \brief hdd_stop() - HDD stop function
4689
4690 This is called in response to ifconfig down
4691
4692 \param - dev Pointer to net_device structure
4693
4694 \return - 0 for success non-zero for failure
4695
4696 --------------------------------------------------------------------------*/
4697
4698int hdd_stop (struct net_device *dev)
4699{
4700 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4701 hdd_context_t *pHddCtx;
4702 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
4703 VOS_STATUS status;
4704 v_BOOL_t enter_standby = TRUE;
4705
4706 ENTER();
4707
4708 if (NULL == pAdapter)
4709 {
4710 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Agarwal Ashish971c2882013-10-30 20:11:12 +05304711 "%s: pAdapter is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004712 return -ENODEV;
4713 }
4714
4715 pHddCtx = (hdd_context_t*)pAdapter->pHddCtx;
4716 if (NULL == pHddCtx)
4717 {
4718 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07004719 "%s: HDD context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004720 return -ENODEV;
4721 }
4722
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004723 clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags);
Jeff Johnson295189b2012-06-20 16:38:30 -07004724 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__);
4725 netif_tx_disable(pAdapter->dev);
4726 netif_carrier_off(pAdapter->dev);
4727
4728
4729 /* SoftAP ifaces should never go in power save mode
4730 making sure same here. */
4731 if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode )
4732 || (WLAN_HDD_MONITOR == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004733 || (WLAN_HDD_P2P_GO == pAdapter->device_mode )
Jeff Johnson295189b2012-06-20 16:38:30 -07004734 )
4735 {
4736 /* SoftAP mode, so return from here */
c_hpothu6ff1c3c2013-10-01 19:01:57 +05304737 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
4738 "%s: In SAP MODE", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07004739 EXIT();
4740 return 0;
4741 }
4742
4743 /* Find if any iface is up then
4744 if any iface is up then can't put device to sleep/ power save mode. */
4745 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
4746 while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) )
4747 {
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004748 if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags))
4749 {
4750 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot "
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05304751 "put device to sleep", __func__);
Jeff Johnson6a81ca42013-04-05 10:37:08 -07004752 enter_standby = FALSE;
4753 break;
4754 }
4755 else
4756 {
4757 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
4758 pAdapterNode = pNext;
4759 }
Jeff Johnson295189b2012-06-20 16:38:30 -07004760 }
4761
4762 if (TRUE == enter_standby)
4763 {
4764 hddLog(VOS_TRACE_LEVEL_INFO, "%s: All Interfaces are Down "
4765 "entering standby", __func__);
4766 if (VOS_STATUS_SUCCESS != wlan_hdd_enter_lowpower(pHddCtx))
4767 {
4768 /*log and return success*/
4769 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to put "
4770 "wlan in power save", __func__);
4771 }
4772 }
4773
4774 EXIT();
4775 return 0;
4776}
4777
4778/**---------------------------------------------------------------------------
4779
4780 \brief hdd_uninit() - HDD uninit function
4781
4782 This is called during the netdev unregister to uninitialize all data
4783associated with the device
4784
4785 \param - dev Pointer to net_device structure
4786
4787 \return - void
4788
4789 --------------------------------------------------------------------------*/
4790static void hdd_uninit (struct net_device *dev)
4791{
4792 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
4793
4794 ENTER();
4795
4796 do
4797 {
4798 if (NULL == pAdapter)
4799 {
4800 hddLog(VOS_TRACE_LEVEL_FATAL,
4801 "%s: NULL pAdapter", __func__);
4802 break;
4803 }
4804
4805 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
4806 {
4807 hddLog(VOS_TRACE_LEVEL_FATAL,
4808 "%s: Invalid magic", __func__);
4809 break;
4810 }
4811
4812 if (NULL == pAdapter->pHddCtx)
4813 {
4814 hddLog(VOS_TRACE_LEVEL_FATAL,
4815 "%s: NULL pHddCtx", __func__);
4816 break;
4817 }
4818
4819 if (dev != pAdapter->dev)
4820 {
4821 hddLog(VOS_TRACE_LEVEL_FATAL,
4822 "%s: Invalid device reference", __func__);
4823 /* we haven't validated all cases so let this go for now */
4824 }
4825
4826 hdd_deinit_adapter(pAdapter->pHddCtx, pAdapter);
4827
4828 /* after uninit our adapter structure will no longer be valid */
4829 pAdapter->dev = NULL;
4830 pAdapter->magic = 0;
4831 } while (0);
4832
4833 EXIT();
4834}
4835
4836/**---------------------------------------------------------------------------
4837
4838 \brief hdd_release_firmware() -
4839
4840 This function calls the release firmware API to free the firmware buffer.
4841
4842 \param - pFileName Pointer to the File Name.
4843 pCtx - Pointer to the adapter .
4844
4845
4846 \return - 0 for success, non zero for failure
4847
4848 --------------------------------------------------------------------------*/
4849
4850VOS_STATUS hdd_release_firmware(char *pFileName,v_VOID_t *pCtx)
4851{
4852 VOS_STATUS status = VOS_STATUS_SUCCESS;
4853 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4854 ENTER();
4855
4856
4857 if (!strcmp(WLAN_FW_FILE, pFileName)) {
4858
4859 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"%s: Loaded firmware file is %s",__func__,pFileName);
4860
4861 if(pHddCtx->fw) {
4862 release_firmware(pHddCtx->fw);
4863 pHddCtx->fw = NULL;
4864 }
4865 else
4866 status = VOS_STATUS_E_FAILURE;
4867 }
4868 else if (!strcmp(WLAN_NV_FILE,pFileName)) {
4869 if(pHddCtx->nv) {
4870 release_firmware(pHddCtx->nv);
4871 pHddCtx->nv = NULL;
4872 }
4873 else
4874 status = VOS_STATUS_E_FAILURE;
4875
4876 }
4877
4878 EXIT();
4879 return status;
4880}
4881
4882/**---------------------------------------------------------------------------
4883
4884 \brief hdd_request_firmware() -
4885
4886 This function reads the firmware file using the request firmware
4887 API and returns the the firmware data and the firmware file size.
4888
4889 \param - pfileName - Pointer to the file name.
4890 - pCtx - Pointer to the adapter .
4891 - ppfw_data - Pointer to the pointer of the firmware data.
4892 - pSize - Pointer to the file size.
4893
4894 \return - VOS_STATUS_SUCCESS for success, VOS_STATUS_E_FAILURE for failure
4895
4896 --------------------------------------------------------------------------*/
4897
4898
4899VOS_STATUS hdd_request_firmware(char *pfileName,v_VOID_t *pCtx,v_VOID_t **ppfw_data, v_SIZE_t *pSize)
4900{
4901 int status;
4902 VOS_STATUS retval = VOS_STATUS_SUCCESS;
4903 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
4904 ENTER();
4905
4906 if( (!strcmp(WLAN_FW_FILE, pfileName)) ) {
4907
4908 status = request_firmware(&pHddCtx->fw, pfileName, pHddCtx->parent_dev);
4909
4910 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
4911 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Firmware %s download failed",
4912 __func__, pfileName);
4913 retval = VOS_STATUS_E_FAILURE;
4914 }
4915
4916 else {
4917 *ppfw_data = (v_VOID_t *)pHddCtx->fw->data;
4918 *pSize = pHddCtx->fw->size;
4919 hddLog(VOS_TRACE_LEVEL_INFO, "%s: Firmware size = %d",
4920 __func__, *pSize);
4921 }
4922 }
4923 else if(!strcmp(WLAN_NV_FILE, pfileName)) {
4924
4925 status = request_firmware(&pHddCtx->nv, pfileName, pHddCtx->parent_dev);
4926
4927 if(status || !pHddCtx->nv || !pHddCtx->nv->data) {
4928 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: nv %s download failed",
4929 __func__, pfileName);
4930 retval = VOS_STATUS_E_FAILURE;
4931 }
4932
4933 else {
4934 *ppfw_data = (v_VOID_t *)pHddCtx->nv->data;
4935 *pSize = pHddCtx->nv->size;
4936 hddLog(VOS_TRACE_LEVEL_INFO, "%s: nv file size = %d",
4937 __func__, *pSize);
4938 }
4939 }
4940
4941 EXIT();
4942 return retval;
4943}
4944/**---------------------------------------------------------------------------
4945 \brief hdd_full_pwr_cbk() - HDD full power callbackfunction
4946
4947 This is the function invoked by SME to inform the result of a full power
4948 request issued by HDD
4949
4950 \param - callbackcontext - Pointer to cookie
4951 status - result of request
4952
4953 \return - None
4954
4955--------------------------------------------------------------------------*/
4956void hdd_full_pwr_cbk(void *callbackContext, eHalStatus status)
4957{
4958 hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext;
4959
Madan Mohan Koyyalamudi8bdd3112012-09-24 13:55:14 -07004960 hddLog(VOS_TRACE_LEVEL_INFO_HIGH,"HDD full Power callback status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004961 if(&pHddCtx->full_pwr_comp_var)
4962 {
4963 complete(&pHddCtx->full_pwr_comp_var);
4964 }
4965}
4966
4967/**---------------------------------------------------------------------------
4968
4969 \brief hdd_req_bmps_cbk() - HDD Request BMPS callback function
4970
4971 This is the function invoked by SME to inform the result of BMPS
4972 request issued by HDD
4973
4974 \param - callbackcontext - Pointer to cookie
4975 status - result of request
4976
4977 \return - None
4978
4979--------------------------------------------------------------------------*/
4980void hdd_req_bmps_cbk(void *callbackContext, eHalStatus status)
4981{
4982
4983 struct completion *completion_var = (struct completion*) callbackContext;
4984
Arif Hussain6d2a3322013-11-17 19:50:10 -08004985 hddLog(VOS_TRACE_LEVEL_ERROR, "HDD BMPS request Callback, status = %d", status);
Jeff Johnson295189b2012-06-20 16:38:30 -07004986 if(completion_var != NULL)
4987 {
4988 complete(completion_var);
4989 }
4990}
4991
4992/**---------------------------------------------------------------------------
4993
4994 \brief hdd_get_cfg_file_size() -
4995
4996 This function reads the configuration file using the request firmware
4997 API and returns the configuration file size.
4998
4999 \param - pCtx - Pointer to the adapter .
5000 - pFileName - Pointer to the file name.
5001 - pBufSize - Pointer to the buffer size.
5002
5003 \return - 0 for success, non zero for failure
5004
5005 --------------------------------------------------------------------------*/
5006
5007VOS_STATUS hdd_get_cfg_file_size(v_VOID_t *pCtx, char *pFileName, v_SIZE_t *pBufSize)
5008{
5009 int status;
5010 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5011
5012 ENTER();
5013
5014 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5015
5016 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5017 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5018 status = VOS_STATUS_E_FAILURE;
5019 }
5020 else {
5021 *pBufSize = pHddCtx->fw->size;
5022 hddLog(VOS_TRACE_LEVEL_INFO, "%s: CFG size = %d", __func__, *pBufSize);
5023 release_firmware(pHddCtx->fw);
5024 pHddCtx->fw = NULL;
5025 }
5026
5027 EXIT();
5028 return VOS_STATUS_SUCCESS;
5029}
5030
5031/**---------------------------------------------------------------------------
5032
5033 \brief hdd_read_cfg_file() -
5034
5035 This function reads the configuration file using the request firmware
5036 API and returns the cfg data and the buffer size of the configuration file.
5037
5038 \param - pCtx - Pointer to the adapter .
5039 - pFileName - Pointer to the file name.
5040 - pBuffer - Pointer to the data buffer.
5041 - pBufSize - Pointer to the buffer size.
5042
5043 \return - 0 for success, non zero for failure
5044
5045 --------------------------------------------------------------------------*/
5046
5047VOS_STATUS hdd_read_cfg_file(v_VOID_t *pCtx, char *pFileName,
5048 v_VOID_t *pBuffer, v_SIZE_t *pBufSize)
5049{
5050 int status;
5051 hdd_context_t *pHddCtx = (hdd_context_t*)pCtx;
5052
5053 ENTER();
5054
5055 status = request_firmware(&pHddCtx->fw, pFileName, pHddCtx->parent_dev);
5056
5057 if(status || !pHddCtx->fw || !pHddCtx->fw->data) {
5058 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: CFG download failed",__func__);
5059 return VOS_STATUS_E_FAILURE;
5060 }
5061 else {
5062 if(*pBufSize != pHddCtx->fw->size) {
5063 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Caller sets invalid CFG "
5064 "file size", __func__);
5065 release_firmware(pHddCtx->fw);
5066 pHddCtx->fw = NULL;
5067 return VOS_STATUS_E_FAILURE;
5068 }
5069 else {
5070 if(pBuffer) {
5071 vos_mem_copy(pBuffer,pHddCtx->fw->data,*pBufSize);
5072 }
5073 release_firmware(pHddCtx->fw);
5074 pHddCtx->fw = NULL;
5075 }
5076 }
5077
5078 EXIT();
5079
5080 return VOS_STATUS_SUCCESS;
5081}
5082
5083/**---------------------------------------------------------------------------
5084
Jeff Johnson295189b2012-06-20 16:38:30 -07005085 \brief hdd_set_mac_address() -
5086
5087 This function sets the user specified mac address using
5088 the command ifconfig wlanX hw ether <mac adress>.
5089
5090 \param - dev - Pointer to the net device.
5091 - addr - Pointer to the sockaddr.
5092 \return - 0 for success, non zero for failure
5093
5094 --------------------------------------------------------------------------*/
5095
5096static int hdd_set_mac_address(struct net_device *dev, void *addr)
5097{
5098 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
5099 struct sockaddr *psta_mac_addr = addr;
5100 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5101
5102 ENTER();
5103
5104 memcpy(&pAdapter->macAddressCurrent, psta_mac_addr->sa_data, ETH_ALEN);
5105
5106#ifdef HDD_SESSIONIZE
5107 // set the MAC address though the STA ID CFG.
5108 halStatus = ccmCfgSetStr( pAdapter->hHal, WNI_CFG_STA_ID,
5109 (v_U8_t *)&pAdapter->macAddressCurrent,
5110 sizeof( pAdapter->macAddressCurrent ),
5111 hdd_set_mac_addr_cb, VOS_FALSE );
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305112
5113 if(eHAL_STATUS_SUCCESS != halStatus)
5114 {
5115 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5116 "%s: failed to set MAC address in CFG", __func__);
5117 }
5118
Jeff Johnson295189b2012-06-20 16:38:30 -07005119#endif
5120
5121 memcpy(dev->dev_addr, psta_mac_addr->sa_data, ETH_ALEN);
5122
5123 EXIT();
5124 return halStatus;
5125}
5126
5127tANI_U8* wlan_hdd_get_intf_addr(hdd_context_t* pHddCtx)
5128{
5129 int i;
5130 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5131 {
Abhishek Singheb183782014-02-06 13:37:21 +05305132 if( 0 == ((pHddCtx->cfg_ini->intfAddrMask) & (1 << i)) )
Jeff Johnson295189b2012-06-20 16:38:30 -07005133 break;
5134 }
5135
5136 if( VOS_MAX_CONCURRENCY_PERSONA == i)
5137 return NULL;
5138
5139 pHddCtx->cfg_ini->intfAddrMask |= (1 << i);
5140 return &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0];
5141}
5142
5143void wlan_hdd_release_intf_addr(hdd_context_t* pHddCtx, tANI_U8* releaseAddr)
5144{
5145 int i;
5146 for ( i = 0; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
5147 {
5148 if ( !memcmp(releaseAddr, &pHddCtx->cfg_ini->intfMacAddr[i].bytes[0], 6) )
5149 {
5150 pHddCtx->cfg_ini->intfAddrMask &= ~(1 << i);
5151 break;
5152 }
5153 }
5154 return;
5155}
5156
5157#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5158 static struct net_device_ops wlan_drv_ops = {
5159 .ndo_open = hdd_open,
5160 .ndo_stop = hdd_stop,
5161 .ndo_uninit = hdd_uninit,
5162 .ndo_start_xmit = hdd_hard_start_xmit,
5163 .ndo_tx_timeout = hdd_tx_timeout,
5164 .ndo_get_stats = hdd_stats,
5165 .ndo_do_ioctl = hdd_ioctl,
5166 .ndo_set_mac_address = hdd_set_mac_address,
5167 .ndo_select_queue = hdd_select_queue,
5168#ifdef WLAN_FEATURE_PACKET_FILTERING
5169#if (LINUX_VERSION_CODE > KERNEL_VERSION(3,1,0))
5170 .ndo_set_rx_mode = hdd_set_multicast_list,
5171#else
5172 .ndo_set_multicast_list = hdd_set_multicast_list,
5173#endif //LINUX_VERSION_CODE
5174#endif
5175 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005176 static struct net_device_ops wlan_mon_drv_ops = {
5177 .ndo_open = hdd_mon_open,
5178 .ndo_stop = hdd_stop,
5179 .ndo_uninit = hdd_uninit,
5180 .ndo_start_xmit = hdd_mon_hard_start_xmit,
5181 .ndo_tx_timeout = hdd_tx_timeout,
5182 .ndo_get_stats = hdd_stats,
5183 .ndo_do_ioctl = hdd_ioctl,
5184 .ndo_set_mac_address = hdd_set_mac_address,
5185 };
Jeff Johnson295189b2012-06-20 16:38:30 -07005186
5187#endif
5188
5189void hdd_set_station_ops( struct net_device *pWlanDev )
5190{
5191#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
Jeff Johnson295189b2012-06-20 16:38:30 -07005192 pWlanDev->netdev_ops = &wlan_drv_ops;
5193#else
5194 pWlanDev->open = hdd_open;
5195 pWlanDev->stop = hdd_stop;
5196 pWlanDev->uninit = hdd_uninit;
5197 pWlanDev->hard_start_xmit = NULL;
5198 pWlanDev->tx_timeout = hdd_tx_timeout;
5199 pWlanDev->get_stats = hdd_stats;
5200 pWlanDev->do_ioctl = hdd_ioctl;
Jeff Johnson295189b2012-06-20 16:38:30 -07005201 pWlanDev->set_mac_address = hdd_set_mac_address;
5202#endif
5203}
5204
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005205static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMacAddr macAddr, const char* name )
Jeff Johnson295189b2012-06-20 16:38:30 -07005206{
5207 struct net_device *pWlanDev = NULL;
5208 hdd_adapter_t *pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07005209 /*
5210 * cfg80211 initialization and registration....
5211 */
5212 pWlanDev = alloc_netdev_mq(sizeof( hdd_adapter_t ), name, ether_setup, NUM_TX_QUEUES);
5213
Jeff Johnson295189b2012-06-20 16:38:30 -07005214 if(pWlanDev != NULL)
5215 {
5216
5217 //Save the pointer to the net_device in the HDD adapter
5218 pAdapter = (hdd_adapter_t*) netdev_priv( pWlanDev );
5219
Jeff Johnson295189b2012-06-20 16:38:30 -07005220 vos_mem_zero( pAdapter, sizeof( hdd_adapter_t ) );
5221
5222 pAdapter->dev = pWlanDev;
5223 pAdapter->pHddCtx = pHddCtx;
5224 pAdapter->magic = WLAN_HDD_ADAPTER_MAGIC;
5225
5226 init_completion(&pAdapter->session_open_comp_var);
5227 init_completion(&pAdapter->session_close_comp_var);
5228 init_completion(&pAdapter->disconnect_comp_var);
5229 init_completion(&pAdapter->linkup_event_var);
5230 init_completion(&pAdapter->cancel_rem_on_chan_var);
5231 init_completion(&pAdapter->rem_on_chan_ready_event);
Jeff Johnson295189b2012-06-20 16:38:30 -07005232#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38))
5233 init_completion(&pAdapter->offchannel_tx_event);
5234#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005235 init_completion(&pAdapter->tx_action_cnf_event);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005236#ifdef FEATURE_WLAN_TDLS
5237 init_completion(&pAdapter->tdls_add_station_comp);
Gopichand Nakkalae7cbc5d2013-03-27 21:09:23 -07005238 init_completion(&pAdapter->tdls_del_station_comp);
Gopichand Nakkalab977a972013-02-18 19:15:09 -08005239 init_completion(&pAdapter->tdls_mgmt_comp);
Gopichand Nakkala79ff85d2013-05-27 17:05:29 +05305240 init_completion(&pAdapter->tdls_link_establish_req_comp);
Hoonki Lee11f7dda2013-02-14 16:55:44 -08005241#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005242 init_completion(&pHddCtx->mc_sus_event_var);
5243 init_completion(&pHddCtx->tx_sus_event_var);
Gopichand Nakkala05621412013-06-19 19:37:38 +05305244 init_completion(&pHddCtx->rx_sus_event_var);
Jeff Johnson9efb9aa2013-03-15 13:59:27 -07005245 init_completion(&pAdapter->ula_complete);
Sameer Thalappilda4eb6a2013-09-25 11:45:07 -07005246 init_completion(&pAdapter->change_country_code);
Jeff Johnson295189b2012-06-20 16:38:30 -07005247
Rajeev79dbe4c2013-10-05 11:03:42 +05305248#ifdef FEATURE_WLAN_BATCH_SCAN
5249 init_completion(&pAdapter->hdd_set_batch_scan_req_var);
5250 init_completion(&pAdapter->hdd_get_batch_scan_req_var);
5251 pAdapter->pBatchScanRsp = NULL;
5252 pAdapter->numScanList = 0;
Rajeev Kumar20140c12013-10-21 19:39:02 -07005253 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
Kiet Lamaa8e15a2014-02-11 23:30:06 -08005254 pAdapter->prev_batch_id = 0;
Rajeev79dbe4c2013-10-05 11:03:42 +05305255 mutex_init(&pAdapter->hdd_batch_scan_lock);
5256#endif
5257
Jeff Johnson295189b2012-06-20 16:38:30 -07005258 pAdapter->isLinkUpSvcNeeded = FALSE;
5259 pAdapter->higherDtimTransition = eANI_BOOLEAN_TRUE;
5260 //Init the net_device structure
5261 strlcpy(pWlanDev->name, name, IFNAMSIZ);
5262
5263 vos_mem_copy(pWlanDev->dev_addr, (void *)macAddr, sizeof(tSirMacAddr));
5264 vos_mem_copy( pAdapter->macAddressCurrent.bytes, macAddr, sizeof(tSirMacAddr));
5265 pWlanDev->watchdog_timeo = HDD_TX_TIMEOUT;
5266 pWlanDev->hard_header_len += LIBRA_HW_NEEDED_HEADROOM;
5267
5268 hdd_set_station_ops( pAdapter->dev );
5269
5270 pWlanDev->destructor = free_netdev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005271 pWlanDev->ieee80211_ptr = &pAdapter->wdev ;
5272 pAdapter->wdev.wiphy = pHddCtx->wiphy;
5273 pAdapter->wdev.netdev = pWlanDev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005274 /* set pWlanDev's parent to underlying device */
5275 SET_NETDEV_DEV(pWlanDev, pHddCtx->parent_dev);
5276 }
5277
5278 return pAdapter;
5279}
5280
5281VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_held )
5282{
5283 struct net_device *pWlanDev = pAdapter->dev;
5284 //hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5285 //hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5286 //eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5287
5288 if( rtnl_lock_held )
5289 {
Madan Mohan Koyyalamudid8ac8662012-11-06 19:04:56 -08005290 if (strnchr(pWlanDev->name, strlen(pWlanDev->name), '%')) {
Jeff Johnson295189b2012-06-20 16:38:30 -07005291 if( dev_alloc_name(pWlanDev, pWlanDev->name) < 0 )
5292 {
5293 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:dev_alloc_name",__func__);
5294 return VOS_STATUS_E_FAILURE;
5295 }
5296 }
5297 if (register_netdevice(pWlanDev))
5298 {
5299 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:register_netdev",__func__);
5300 return VOS_STATUS_E_FAILURE;
5301 }
5302 }
5303 else
5304 {
5305 if(register_netdev(pWlanDev))
5306 {
5307 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed:register_netdev",__func__);
5308 return VOS_STATUS_E_FAILURE;
5309 }
5310 }
5311 set_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags);
5312
5313 return VOS_STATUS_SUCCESS;
5314}
5315
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005316static eHalStatus hdd_smeCloseSessionCallback(void *pContext)
Jeff Johnson295189b2012-06-20 16:38:30 -07005317{
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005318 hdd_adapter_t *pAdapter = pContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07005319
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005320 if (NULL == pAdapter)
5321 {
5322 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__);
5323 return eHAL_STATUS_INVALID_PARAMETER;
Jeff Johnson295189b2012-06-20 16:38:30 -07005324 }
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005325
5326 if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic)
5327 {
5328 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__);
5329 return eHAL_STATUS_NOT_INITIALIZED;
5330 }
5331
5332 clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags);
5333
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005334#ifndef WLAN_OPEN_SOURCE
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005335 /* need to make sure all of our scheduled work has completed.
5336 * This callback is called from MC thread context, so it is safe to
5337 * to call below flush workqueue API from here.
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005338 *
5339 * Even though this is called from MC thread context, if there is a faulty
5340 * work item in the system, that can hang this call forever. So flushing
5341 * this global work queue is not safe; and now we make sure that
5342 * individual work queues are stopped correctly. But the cancel work queue
5343 * is a GPL only API, so the proprietary version of the driver would still
5344 * rely on the global work queue flush.
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005345 */
5346 flush_scheduled_work();
Sameer Thalappilbee426e2013-10-30 10:30:30 -07005347#endif
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005348
5349 /* We can be blocked while waiting for scheduled work to be
5350 * flushed, and the adapter structure can potentially be freed, in
5351 * which case the magic will have been reset. So make sure the
5352 * magic is still good, and hence the adapter structure is still
5353 * valid, before signaling completion */
5354 if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic)
5355 {
5356 complete(&pAdapter->session_close_comp_var);
5357 }
5358
Jeff Johnson295189b2012-06-20 16:38:30 -07005359 return eHAL_STATUS_SUCCESS;
5360}
5361
5362VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter )
5363{
5364 struct net_device *pWlanDev = pAdapter->dev;
5365 hdd_station_ctx_t *pHddStaCtx = &pAdapter->sessionCtx.station;
5366 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter );
5367 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
5368 VOS_STATUS status = VOS_STATUS_E_FAILURE;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305369 long rc = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07005370
5371 INIT_COMPLETION(pAdapter->session_open_comp_var);
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005372 sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode);
Jeff Johnson295189b2012-06-20 16:38:30 -07005373 //Open a SME session for future operation
5374 halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter,
Kiran Kumar Lokere0ad5cd32013-06-25 11:26:22 -07005375 (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId);
Jeff Johnson295189b2012-06-20 16:38:30 -07005376 if ( !HAL_STATUS_SUCCESS( halStatus ) )
5377 {
5378 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005379 "sme_OpenSession() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005380 halStatus, halStatus );
5381 status = VOS_STATUS_E_FAILURE;
5382 goto error_sme_open;
5383 }
5384
5385 //Block on a completion variable. Can't wait forever though.
5386 rc = wait_for_completion_interruptible_timeout(
5387 &pAdapter->session_open_comp_var,
5388 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305389 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005390 {
5391 hddLog(VOS_TRACE_LEVEL_FATAL,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305392 "Session is not opened within timeout period code %ld", rc );
Jeff Johnson295189b2012-06-20 16:38:30 -07005393 status = VOS_STATUS_E_FAILURE;
5394 goto error_sme_open;
5395 }
5396
5397 // Register wireless extensions
5398 if( eHAL_STATUS_SUCCESS != (halStatus = hdd_register_wext(pWlanDev)))
5399 {
5400 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005401 "hdd_register_wext() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005402 halStatus, halStatus );
5403 status = VOS_STATUS_E_FAILURE;
5404 goto error_register_wext;
5405 }
5406 //Safe to register the hard_start_xmit function again
5407#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29))
5408 wlan_drv_ops.ndo_start_xmit = hdd_hard_start_xmit;
5409#else
5410 pWlanDev->hard_start_xmit = hdd_hard_start_xmit;
5411#endif
5412
5413 //Set the Connection State to Not Connected
5414 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
5415
5416 //Set the default operation channel
5417 pHddStaCtx->conn_info.operationChannel = pHddCtx->cfg_ini->OperatingChannel;
5418
5419 /* Make the default Auth Type as OPEN*/
5420 pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM;
5421
5422 if( VOS_STATUS_SUCCESS != ( status = hdd_init_tx_rx( pAdapter ) ) )
5423 {
5424 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005425 "hdd_init_tx_rx() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005426 status, status );
5427 goto error_init_txrx;
5428 }
5429
5430 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5431
5432 if( VOS_STATUS_SUCCESS != ( status = hdd_wmm_adapter_init( pAdapter ) ) )
5433 {
5434 hddLog(VOS_TRACE_LEVEL_FATAL,
Jeff Johnson0299d0a2013-10-30 12:37:43 -07005435 "hdd_wmm_adapter_init() failed with status code %08d [x%08x]",
Jeff Johnson295189b2012-06-20 16:38:30 -07005436 status, status );
5437 goto error_wmm_init;
5438 }
5439
5440 set_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5441
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005442#ifdef FEATURE_WLAN_TDLS
5443 if(0 != wlan_hdd_tdls_init(pAdapter))
5444 {
5445 status = VOS_STATUS_E_FAILURE;
5446 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wlan_hdd_tdls_init failed",__func__);
5447 goto error_tdls_init;
5448 }
5449 set_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5450#endif
5451
Jeff Johnson295189b2012-06-20 16:38:30 -07005452 return VOS_STATUS_SUCCESS;
5453
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005454#ifdef FEATURE_WLAN_TDLS
5455error_tdls_init:
5456 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5457 hdd_wmm_adapter_close(pAdapter);
5458#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005459error_wmm_init:
5460 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5461 hdd_deinit_tx_rx(pAdapter);
5462error_init_txrx:
5463 hdd_UnregisterWext(pWlanDev);
5464error_register_wext:
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005465 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
Jeff Johnson295189b2012-06-20 16:38:30 -07005466 {
5467 INIT_COMPLETION(pAdapter->session_close_comp_var);
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005468 if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal,
Jeff Johnson295189b2012-06-20 16:38:30 -07005469 pAdapter->sessionId,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005470 hdd_smeCloseSessionCallback, pAdapter))
Jeff Johnson295189b2012-06-20 16:38:30 -07005471 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305472 unsigned long rc;
5473
Jeff Johnson295189b2012-06-20 16:38:30 -07005474 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305475 rc = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07005476 &pAdapter->session_close_comp_var,
Jeff Johnsonc6ab5b92013-04-15 17:02:05 -07005477 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305478 if (rc <= 0)
5479 hddLog(VOS_TRACE_LEVEL_ERROR,
5480 FL("Session is not opened within timeout period code %ld"), rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005481 }
5482}
5483error_sme_open:
5484 return status;
5485}
5486
Jeff Johnson295189b2012-06-20 16:38:30 -07005487void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5488{
5489 hdd_cfg80211_state_t *cfgState;
5490
5491 cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter );
5492
5493 if( NULL != cfgState->buf )
5494 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305495 long rc;
Jeff Johnson295189b2012-06-20 16:38:30 -07005496 INIT_COMPLETION(pAdapter->tx_action_cnf_event);
5497 rc = wait_for_completion_interruptible_timeout(
5498 &pAdapter->tx_action_cnf_event,
5499 msecs_to_jiffies(ACTION_FRAME_TX_TIMEOUT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305500 if (rc <= 0)
Jeff Johnson295189b2012-06-20 16:38:30 -07005501 {
Sudhir Sattayappa Kohalli8ee532d2013-02-15 13:16:26 -08005502 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305503 "%s ERROR: HDD Wait for Action Confirmation Failed!! %ld"
5504 , __func__, rc);
Jeff Johnson295189b2012-06-20 16:38:30 -07005505 }
5506 }
5507 return;
5508}
Jeff Johnson295189b2012-06-20 16:38:30 -07005509
5510void hdd_deinit_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
5511{
5512 ENTER();
5513 switch ( pAdapter->device_mode )
5514 {
5515 case WLAN_HDD_INFRA_STATION:
5516 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005517 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005518 {
5519 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5520 {
5521 hdd_deinit_tx_rx( pAdapter );
5522 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5523 }
5524
5525 if(test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5526 {
5527 hdd_wmm_adapter_close( pAdapter );
5528 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5529 }
5530
Jeff Johnson295189b2012-06-20 16:38:30 -07005531 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Gopichand Nakkala4327a152013-03-04 23:22:42 -08005532#ifdef FEATURE_WLAN_TDLS
5533 if(test_bit(TDLS_INIT_DONE, &pAdapter->event_flags))
5534 {
5535 wlan_hdd_tdls_exit(pAdapter);
5536 clear_bit(TDLS_INIT_DONE, &pAdapter->event_flags);
5537 }
5538#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005539
5540 break;
5541 }
5542
5543 case WLAN_HDD_SOFTAP:
5544 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005545 {
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05305546
5547 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
5548 {
5549 hdd_wmm_adapter_close( pAdapter );
5550 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
5551 }
5552
Jeff Johnson295189b2012-06-20 16:38:30 -07005553 hdd_cleanup_actionframe(pHddCtx, pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07005554
5555 hdd_unregister_hostapd(pAdapter);
5556 hdd_set_conparam( 0 );
Jeff Johnson295189b2012-06-20 16:38:30 -07005557 wlan_hdd_set_monitor_tx_adapter( WLAN_HDD_GET_CTX(pAdapter), NULL );
Jeff Johnson295189b2012-06-20 16:38:30 -07005558 break;
5559 }
5560
5561 case WLAN_HDD_MONITOR:
5562 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005563 hdd_adapter_t* pAdapterforTx = pAdapter->sessionCtx.monitor.pAdapterForTx;
Jeff Johnson295189b2012-06-20 16:38:30 -07005564 if(test_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags))
5565 {
5566 hdd_deinit_tx_rx( pAdapter );
5567 clear_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5568 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005569 if(NULL != pAdapterforTx)
5570 {
5571 hdd_cleanup_actionframe(pHddCtx, pAdapterforTx);
5572 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005573 break;
5574 }
5575
5576
5577 default:
5578 break;
5579 }
5580
5581 EXIT();
5582}
5583
5584void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_U8 rtnl_held )
5585{
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08005586 struct net_device *pWlanDev = NULL;
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305587
5588 ENTER();
5589 if (NULL == pAdapter)
5590 {
5591 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5592 "%s: HDD adapter is Null", __func__);
5593 return;
5594 }
5595
5596 pWlanDev = pAdapter->dev;
Jeff Johnson295189b2012-06-20 16:38:30 -07005597
Rajeev79dbe4c2013-10-05 11:03:42 +05305598#ifdef FEATURE_WLAN_BATCH_SCAN
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305599 if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION)
5600 || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)
Rajeev Kumarf999e582014-01-09 17:33:29 -08005601 || (pAdapter->device_mode == WLAN_HDD_P2P_GO)
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305602 || (pAdapter->device_mode == WLAN_HDD_P2P_DEVICE)
5603 )
5604 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005605 if (pAdapter)
Rajeev79dbe4c2013-10-05 11:03:42 +05305606 {
Rajeev Kumarf999e582014-01-09 17:33:29 -08005607 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
5608 {
5609 hdd_deinit_batch_scan(pAdapter);
5610 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305611 }
Rajeev Kumarf999e582014-01-09 17:33:29 -08005612 }
Rajeev79dbe4c2013-10-05 11:03:42 +05305613#endif
5614
Jeff Johnson295189b2012-06-20 16:38:30 -07005615 if(test_bit(NET_DEVICE_REGISTERED, &pAdapter->event_flags)) {
5616 if( rtnl_held )
5617 {
5618 unregister_netdevice(pWlanDev);
5619 }
5620 else
5621 {
5622 unregister_netdev(pWlanDev);
5623 }
5624 // note that the pAdapter is no longer valid at this point
5625 // since the memory has been reclaimed
5626 }
5627
Srinivas, Dasari693dfc52013-12-27 17:29:09 +05305628 EXIT();
Jeff Johnson295189b2012-06-20 16:38:30 -07005629}
5630
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005631void hdd_set_pwrparams(hdd_context_t *pHddCtx)
5632{
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305633 VOS_STATUS status;
5634 hdd_adapter_t *pAdapter = NULL;
5635 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005636
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305637 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005638
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305639 /*loop through all adapters.*/
5640 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005641 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305642 pAdapter = pAdapterNode->pAdapter;
5643 if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode)
5644 && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) )
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005645
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305646 { // we skip this registration for modes other than STA and P2P client modes.
5647 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5648 pAdapterNode = pNext;
5649 continue;
5650 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005651
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305652 //Apply Dynamic DTIM For P2P
5653 //Only if ignoreDynamicDtimInP2pMode is not set in ini
5654 if ((pHddCtx->cfg_ini->enableDynamicDTIM ||
5655 pHddCtx->cfg_ini->enableModulatedDTIM) &&
5656 ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
5657 ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) &&
5658 !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) &&
5659 (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) &&
5660 (eConnectionState_Associated ==
5661 (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) &&
5662 (pHddCtx->cfg_ini->fIsBmpsEnabled))
5663 {
5664 tSirSetPowerParamsReq powerRequest = { 0 };
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005665
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05305666 powerRequest.uIgnoreDTIM = 1;
5667 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
5668
5669 if (pHddCtx->cfg_ini->enableModulatedDTIM)
5670 {
5671 powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM;
5672 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
5673 }
5674 else
5675 {
5676 powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM;
5677 }
5678
5679 /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM
5680 * specified during Enter/Exit BMPS when LCD off*/
5681 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5682 NULL, eANI_BOOLEAN_FALSE);
5683 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5684 NULL, eANI_BOOLEAN_FALSE);
5685
5686 /* switch to the DTIM specified in cfg.ini */
5687 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5688 "Switch to DTIM %d", powerRequest.uListenInterval);
5689 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5690 break;
5691
5692 }
5693
5694 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
5695 pAdapterNode = pNext;
5696 }
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005697}
5698
5699void hdd_reset_pwrparams(hdd_context_t *pHddCtx)
5700{
5701 /*Switch back to DTIM 1*/
5702 tSirSetPowerParamsReq powerRequest = { 0 };
5703
5704 powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value;
5705 powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value;
Yue Mac24062f2013-05-13 17:01:29 -07005706 powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM;
Tushnim Bhattacharyya3a37def2013-02-24 11:11:15 -08005707
5708 /* Update ignoreDTIM and ListedInterval in CFG with default values */
5709 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM,
5710 NULL, eANI_BOOLEAN_FALSE);
5711 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval,
5712 NULL, eANI_BOOLEAN_FALSE);
5713
5714 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
5715 "Switch to DTIM%d",powerRequest.uListenInterval);
5716 sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE);
5717
5718}
5719
Jeff Johnson295189b2012-06-20 16:38:30 -07005720VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx)
5721{
5722 VOS_STATUS status = VOS_STATUS_SUCCESS;
5723
5724 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5725 {
5726 sme_EnablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5727 }
5728
5729 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5730 {
5731 sme_StartAutoBmpsTimer(pHddCtx->hHal);
5732 }
5733
5734 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5735 {
5736 sme_EnablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5737 }
5738
5739 return status;
5740}
5741
5742VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type)
5743{
5744 hdd_adapter_t *pAdapter = NULL;
5745 eHalStatus halStatus;
5746 VOS_STATUS status = VOS_STATUS_E_INVAL;
5747 v_BOOL_t disableBmps = FALSE;
5748 v_BOOL_t disableImps = FALSE;
5749
5750 switch(session_type)
5751 {
5752 case WLAN_HDD_INFRA_STATION:
5753 case WLAN_HDD_SOFTAP:
Jeff Johnson295189b2012-06-20 16:38:30 -07005754 case WLAN_HDD_P2P_CLIENT:
5755 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005756 //Exit BMPS -> Is Sta/P2P Client is already connected
5757 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
5758 if((NULL != pAdapter)&&
5759 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5760 {
5761 disableBmps = TRUE;
5762 }
5763
5764 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
5765 if((NULL != pAdapter)&&
5766 hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR(pAdapter)))
5767 {
5768 disableBmps = TRUE;
5769 }
5770
5771 //Exit both Bmps and Imps incase of Go/SAP Mode
5772 if((WLAN_HDD_SOFTAP == session_type) ||
5773 (WLAN_HDD_P2P_GO == session_type))
5774 {
5775 disableBmps = TRUE;
5776 disableImps = TRUE;
5777 }
5778
5779 if(TRUE == disableImps)
5780 {
5781 if (pHddCtx->cfg_ini->fIsImpsEnabled)
5782 {
5783 sme_DisablePowerSave (pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
5784 }
5785 }
5786
5787 if(TRUE == disableBmps)
5788 {
5789 if(pHddCtx->cfg_ini->fIsBmpsEnabled)
5790 {
5791 halStatus = sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
5792
5793 if(eHAL_STATUS_SUCCESS != halStatus)
5794 {
5795 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005796 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Disable Power Save", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005797 VOS_ASSERT(0);
5798 return status;
5799 }
5800 }
5801
5802 if(pHddCtx->cfg_ini->fIsAutoBmpsTimerEnabled)
5803 {
5804 halStatus = sme_StopAutoBmpsTimer(pHddCtx->hHal);
5805
5806 if(eHAL_STATUS_SUCCESS != halStatus)
5807 {
5808 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005809 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Stop Auto Bmps Timer", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005810 VOS_ASSERT(0);
5811 return status;
5812 }
5813 }
5814 }
5815
5816 if((TRUE == disableBmps) ||
5817 (TRUE == disableImps))
5818 {
5819 /* Now, get the chip into Full Power now */
5820 INIT_COMPLETION(pHddCtx->full_pwr_comp_var);
5821 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_pwr_cbk,
5822 pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD);
5823
5824 if(halStatus != eHAL_STATUS_SUCCESS)
5825 {
5826 if(halStatus == eHAL_STATUS_PMC_PENDING)
5827 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305828 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07005829 //Block on a completion variable. Can't wait forever though
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305830 ret = wait_for_completion_interruptible_timeout(
5831 &pHddCtx->full_pwr_comp_var,
5832 msecs_to_jiffies(1000));
5833 if (ret <= 0)
5834 {
5835 hddLog(VOS_TRACE_LEVEL_ERROR,
5836 "%s: wait on full_pwr_comp_var failed %ld",
5837 __func__, ret);
5838 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005839 }
5840 else
5841 {
5842 status = VOS_STATUS_E_FAILURE;
Arif Hussain6d2a3322013-11-17 19:50:10 -08005843 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Request for Full Power failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005844 VOS_ASSERT(0);
5845 return status;
5846 }
5847 }
5848
5849 status = VOS_STATUS_SUCCESS;
5850 }
5851
5852 break;
5853 }
5854 return status;
5855}
5856
5857hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type,
Jeff Johnsoneed415b2013-01-18 16:11:20 -08005858 const char *iface_name, tSirMacAddr macAddr,
Jeff Johnson295189b2012-06-20 16:38:30 -07005859 tANI_U8 rtnl_held )
5860{
5861 hdd_adapter_t *pAdapter = NULL;
5862 hdd_adapter_list_node_t *pHddAdapterNode = NULL;
5863 VOS_STATUS status = VOS_STATUS_E_FAILURE;
5864 VOS_STATUS exitbmpsStatus;
5865
Arif Hussain6d2a3322013-11-17 19:50:10 -08005866 hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s iface =%s type = %d",__func__,iface_name,session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005867
5868 //Disable BMPS incase of Concurrency
5869 exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, session_type);
5870
5871 if(VOS_STATUS_E_FAILURE == exitbmpsStatus)
5872 {
5873 //Fail to Exit BMPS
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305874 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Fail to Exit BMPS", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07005875 VOS_ASSERT(0);
5876 return NULL;
5877 }
5878
5879 switch(session_type)
5880 {
5881 case WLAN_HDD_INFRA_STATION:
Jeff Johnson295189b2012-06-20 16:38:30 -07005882 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07005883 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07005884 {
5885 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5886
5887 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305888 {
5889 hddLog(VOS_TRACE_LEVEL_FATAL,
5890 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005891 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305892 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005893
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305894#ifdef FEATURE_WLAN_TDLS
5895 /* A Mutex Lock is introduced while changing/initializing the mode to
5896 * protect the concurrent access for the Adapters by TDLS module.
5897 */
5898 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
5899 {
5900 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
5901 "%s: unable to lock list", __func__);
5902 return NULL;
5903 }
5904#endif
5905
Jeff Johnsone7245742012-09-05 17:12:55 -07005906 pAdapter->wdev.iftype = (session_type == WLAN_HDD_P2P_CLIENT) ?
5907 NL80211_IFTYPE_P2P_CLIENT:
5908 NL80211_IFTYPE_STATION;
Jeff Johnson295189b2012-06-20 16:38:30 -07005909
Jeff Johnson295189b2012-06-20 16:38:30 -07005910 pAdapter->device_mode = session_type;
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05305911#ifdef FEATURE_WLAN_TDLS
5912 mutex_unlock(&pHddCtx->tdls_lock);
5913#endif
Sunil Dutt66485cb2013-12-19 19:05:03 +05305914
5915 status = hdd_init_station_mode( pAdapter );
Jeff Johnson295189b2012-06-20 16:38:30 -07005916 if( VOS_STATUS_SUCCESS != status )
5917 goto err_free_netdev;
5918
5919 status = hdd_register_interface( pAdapter, rtnl_held );
5920 if( VOS_STATUS_SUCCESS != status )
5921 {
5922 hdd_deinit_adapter(pHddCtx, pAdapter);
5923 goto err_free_netdev;
5924 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305925
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05305926 // Workqueue which gets scheduled in IPv4 notification callback.
5927 INIT_WORK(&pAdapter->ipv4NotifierWorkQueue, hdd_ipv4_notifier_work_queue);
5928
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05305929#ifdef WLAN_NS_OFFLOAD
5930 // Workqueue which gets scheduled in IPv6 notification callback.
5931 INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue);
5932#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07005933 //Stop the Interface TX queue.
5934 netif_tx_disable(pAdapter->dev);
5935 //netif_tx_disable(pWlanDev);
5936 netif_carrier_off(pAdapter->dev);
5937
5938 break;
5939 }
5940
Jeff Johnson295189b2012-06-20 16:38:30 -07005941 case WLAN_HDD_P2P_GO:
Jeff Johnson295189b2012-06-20 16:38:30 -07005942 case WLAN_HDD_SOFTAP:
5943 {
5944 pAdapter = hdd_wlan_create_ap_dev( pHddCtx, macAddr, (tANI_U8 *)iface_name );
5945 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305946 {
5947 hddLog(VOS_TRACE_LEVEL_FATAL,
5948 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005949 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305950 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005951
Jeff Johnson295189b2012-06-20 16:38:30 -07005952 pAdapter->wdev.iftype = (session_type == WLAN_HDD_SOFTAP) ?
5953 NL80211_IFTYPE_AP:
5954 NL80211_IFTYPE_P2P_GO;
Jeff Johnson295189b2012-06-20 16:38:30 -07005955 pAdapter->device_mode = session_type;
5956
5957 status = hdd_init_ap_mode(pAdapter);
5958 if( VOS_STATUS_SUCCESS != status )
5959 goto err_free_netdev;
5960
5961 status = hdd_register_hostapd( pAdapter, rtnl_held );
5962 if( VOS_STATUS_SUCCESS != status )
5963 {
5964 hdd_deinit_adapter(pHddCtx, pAdapter);
5965 goto err_free_netdev;
5966 }
5967
5968 netif_tx_disable(pAdapter->dev);
5969 netif_carrier_off(pAdapter->dev);
5970
5971 hdd_set_conparam( 1 );
5972 break;
5973 }
5974 case WLAN_HDD_MONITOR:
5975 {
Jeff Johnson295189b2012-06-20 16:38:30 -07005976 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
5977 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305978 {
5979 hddLog(VOS_TRACE_LEVEL_FATAL,
5980 FL("failed to allocate adapter for session %d"), session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07005981 return NULL;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05305982 }
Jeff Johnson295189b2012-06-20 16:38:30 -07005983
5984 pAdapter->wdev.iftype = NL80211_IFTYPE_MONITOR;
5985 pAdapter->device_mode = session_type;
5986 status = hdd_register_interface( pAdapter, rtnl_held );
5987#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
5988 pAdapter->dev->netdev_ops = &wlan_mon_drv_ops;
5989#else
5990 pAdapter->dev->open = hdd_mon_open;
5991 pAdapter->dev->hard_start_xmit = hdd_mon_hard_start_xmit;
5992#endif
5993 hdd_init_tx_rx( pAdapter );
5994 set_bit(INIT_TX_RX_SUCCESS, &pAdapter->event_flags);
5995 //Set adapter to be used for data tx. It will use either GO or softap.
5996 pAdapter->sessionCtx.monitor.pAdapterForTx =
5997 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_SOFTAP);
Jeff Johnson295189b2012-06-20 16:38:30 -07005998 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx)
5999 {
6000 pAdapter->sessionCtx.monitor.pAdapterForTx =
6001 hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_GO);
6002 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006003 /* This workqueue will be used to transmit management packet over
6004 * monitor interface. */
Madan Mohan Koyyalamudic75be962012-10-18 19:19:03 -07006005 if (NULL == pAdapter->sessionCtx.monitor.pAdapterForTx) {
6006 hddLog(VOS_TRACE_LEVEL_ERROR,"%s:Failed:hdd_get_adapter",__func__);
6007 return NULL;
6008 }
Madan Mohan Koyyalamudi9f40ceb2012-10-18 19:22:56 -07006009
Jeff Johnson295189b2012-06-20 16:38:30 -07006010 INIT_WORK(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue,
6011 hdd_mon_tx_work_queue);
Jeff Johnson295189b2012-06-20 16:38:30 -07006012 }
6013 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006014 case WLAN_HDD_FTM:
6015 {
6016 pAdapter = hdd_alloc_station_adapter( pHddCtx, macAddr, iface_name );
6017
6018 if( NULL == pAdapter )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306019 {
6020 hddLog(VOS_TRACE_LEVEL_FATAL,
6021 FL("failed to allocate adapter for session %d"), session_type);
6022 return NULL;
6023 }
6024
Jeff Johnson295189b2012-06-20 16:38:30 -07006025 /* Assign NL80211_IFTYPE_STATION as interface type to resolve Kernel Warning
6026 * message while loading driver in FTM mode. */
6027 pAdapter->wdev.iftype = NL80211_IFTYPE_STATION;
6028 pAdapter->device_mode = session_type;
6029 status = hdd_register_interface( pAdapter, rtnl_held );
Madan Mohan Koyyalamudif89ac9f2013-09-19 16:58:12 +05306030
6031 hdd_init_tx_rx( pAdapter );
6032
6033 //Stop the Interface TX queue.
6034 netif_tx_disable(pAdapter->dev);
6035 netif_carrier_off(pAdapter->dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006036 }
6037 break;
Jeff Johnson295189b2012-06-20 16:38:30 -07006038 default:
6039 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306040 hddLog(VOS_TRACE_LEVEL_FATAL,"%s Invalid session type %d",
6041 __func__, session_type);
Jeff Johnson295189b2012-06-20 16:38:30 -07006042 VOS_ASSERT(0);
6043 return NULL;
6044 }
6045 }
6046
Jeff Johnson295189b2012-06-20 16:38:30 -07006047 if( VOS_STATUS_SUCCESS == status )
6048 {
6049 //Add it to the hdd's session list.
6050 pHddAdapterNode = vos_mem_malloc( sizeof( hdd_adapter_list_node_t ) );
6051 if( NULL == pHddAdapterNode )
6052 {
6053 status = VOS_STATUS_E_NOMEM;
6054 }
6055 else
6056 {
6057 pHddAdapterNode->pAdapter = pAdapter;
6058 status = hdd_add_adapter_back ( pHddCtx,
6059 pHddAdapterNode );
6060 }
6061 }
6062
6063 if( VOS_STATUS_SUCCESS != status )
6064 {
6065 if( NULL != pAdapter )
6066 {
6067 hdd_cleanup_adapter( pHddCtx, pAdapter, rtnl_held );
6068 pAdapter = NULL;
6069 }
6070 if( NULL != pHddAdapterNode )
6071 {
6072 vos_mem_free( pHddAdapterNode );
6073 }
6074
6075 goto resume_bmps;
6076 }
6077
6078 if(VOS_STATUS_SUCCESS == status)
6079 {
6080 wlan_hdd_set_concurrency_mode(pHddCtx, session_type);
6081
Madan Mohan Koyyalamudi96dd30d2012-10-05 17:24:51 -07006082 //Initialize the WoWL service
6083 if(!hdd_init_wowl(pAdapter))
6084 {
6085 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_init_wowl failed",__func__);
6086 goto err_free_netdev;
6087 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006088 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006089 return pAdapter;
6090
6091err_free_netdev:
6092 free_netdev(pAdapter->dev);
6093 wlan_hdd_release_intf_addr( pHddCtx,
6094 pAdapter->macAddressCurrent.bytes );
6095
6096resume_bmps:
6097 //If bmps disabled enable it
6098 if(VOS_STATUS_SUCCESS == exitbmpsStatus)
6099 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306100 if (pHddCtx->hdd_wlan_suspended)
6101 {
6102 hdd_set_pwrparams(pHddCtx);
6103 }
6104 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006105 }
6106 return NULL;
6107}
6108
6109VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter,
6110 tANI_U8 rtnl_held )
6111{
6112 hdd_adapter_list_node_t *pAdapterNode, *pCurrent, *pNext;
6113 VOS_STATUS status;
6114
6115 status = hdd_get_front_adapter ( pHddCtx, &pCurrent );
6116 if( VOS_STATUS_SUCCESS != status )
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306117 {
6118 hddLog(VOS_TRACE_LEVEL_WARN,"%s: adapter list empty %d",
6119 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006120 return status;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306121 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006122
6123 while ( pCurrent->pAdapter != pAdapter )
6124 {
6125 status = hdd_get_next_adapter ( pHddCtx, pCurrent, &pNext );
6126 if( VOS_STATUS_SUCCESS != status )
6127 break;
6128
6129 pCurrent = pNext;
6130 }
6131 pAdapterNode = pCurrent;
6132 if( VOS_STATUS_SUCCESS == status )
6133 {
6134 wlan_hdd_clear_concurrency_mode(pHddCtx, pAdapter->device_mode);
6135 hdd_cleanup_adapter( pHddCtx, pAdapterNode->pAdapter, rtnl_held );
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306136
6137#ifdef FEATURE_WLAN_TDLS
6138
6139 /* A Mutex Lock is introduced while changing/initializing the mode to
6140 * protect the concurrent access for the Adapters by TDLS module.
6141 */
6142 if (mutex_lock_interruptible(&pHddCtx->tdls_lock))
6143 {
6144 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
6145 "%s: unable to lock list", __func__);
6146 return VOS_STATUS_E_FAILURE;
6147 }
6148#endif
6149
Jeff Johnson295189b2012-06-20 16:38:30 -07006150 hdd_remove_adapter( pHddCtx, pAdapterNode );
6151 vos_mem_free( pAdapterNode );
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08006152 pAdapterNode = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07006153
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05306154#ifdef FEATURE_WLAN_TDLS
6155 mutex_unlock(&pHddCtx->tdls_lock);
6156#endif
6157
Jeff Johnson295189b2012-06-20 16:38:30 -07006158
6159 /* If there is a single session of STA/P2P client, re-enable BMPS */
6160 if ((!vos_concurrent_sessions_running()) &&
6161 ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) ||
6162 (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1)))
6163 {
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05306164 if (pHddCtx->hdd_wlan_suspended)
6165 {
6166 hdd_set_pwrparams(pHddCtx);
6167 }
6168 hdd_enable_bmps_imps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07006169 }
6170
6171 return VOS_STATUS_SUCCESS;
6172 }
6173
6174 return VOS_STATUS_E_FAILURE;
6175}
6176
6177VOS_STATUS hdd_close_all_adapters( hdd_context_t *pHddCtx )
6178{
6179 hdd_adapter_list_node_t *pHddAdapterNode;
6180 VOS_STATUS status;
6181
6182 ENTER();
6183
6184 do
6185 {
6186 status = hdd_remove_front_adapter( pHddCtx, &pHddAdapterNode );
6187 if( pHddAdapterNode && VOS_STATUS_SUCCESS == status )
6188 {
6189 hdd_cleanup_adapter( pHddCtx, pHddAdapterNode->pAdapter, FALSE );
6190 vos_mem_free( pHddAdapterNode );
6191 }
6192 }while( NULL != pHddAdapterNode && VOS_STATUS_E_EMPTY != status );
6193
6194 EXIT();
6195
6196 return VOS_STATUS_SUCCESS;
6197}
6198
6199void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter)
6200{
6201 v_U8_t addIE[1] = {0};
6202
6203 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6204 WNI_CFG_PROBE_RSP_ADDNIE_DATA1,(tANI_U8*)addIE, 0, NULL,
6205 eANI_BOOLEAN_FALSE) )
6206 {
6207 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006208 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA1 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006209 }
6210
6211 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6212 WNI_CFG_PROBE_RSP_ADDNIE_DATA2, (tANI_U8*)addIE, 0, NULL,
6213 eANI_BOOLEAN_FALSE) )
6214 {
6215 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006216 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA2 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006217 }
6218
6219 if ( eHAL_STATUS_FAILURE == ccmCfgSetStr((WLAN_HDD_GET_CTX(pHostapdAdapter))->hHal,
6220 WNI_CFG_PROBE_RSP_ADDNIE_DATA3, (tANI_U8*)addIE, 0, NULL,
6221 eANI_BOOLEAN_FALSE) )
6222 {
6223 hddLog(LOGE,
Arif Hussain6d2a3322013-11-17 19:50:10 -08006224 "Could not pass on WNI_CFG_PROBE_RSP_ADDNIE_DATA3 to CCM");
Jeff Johnson295189b2012-06-20 16:38:30 -07006225 }
6226}
6227
6228VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6229{
6230 eHalStatus halStatus = eHAL_STATUS_SUCCESS;
6231 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6232 union iwreq_data wrqu;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306233 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006234
6235 ENTER();
6236
6237 switch(pAdapter->device_mode)
6238 {
6239 case WLAN_HDD_INFRA_STATION:
6240 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006241 case WLAN_HDD_P2P_DEVICE:
Jeff Johnson295189b2012-06-20 16:38:30 -07006242 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6243 {
6244 if (pWextState->roamProfile.BSSType == eCSR_BSS_TYPE_START_IBSS)
6245 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6246 pAdapter->sessionId,
6247 eCSR_DISCONNECT_REASON_IBSS_LEAVE);
6248 else
6249 halStatus = sme_RoamDisconnect(pHddCtx->hHal,
6250 pAdapter->sessionId,
6251 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6252 //success implies disconnect command got queued up successfully
6253 if(halStatus == eHAL_STATUS_SUCCESS)
6254 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306255 ret = wait_for_completion_interruptible_timeout(
6256 &pAdapter->disconnect_comp_var,
6257 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
6258 if (ret <= 0)
6259 {
6260 hddLog(VOS_TRACE_LEVEL_ERROR,
6261 "%s: wait on disconnect_comp_var failed %ld",
6262 __func__, ret);
6263 }
6264 }
6265 else
6266 {
6267 hddLog(LOGE, "%s: failed to post disconnect event to SME",
6268 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006269 }
6270 memset(&wrqu, '\0', sizeof(wrqu));
6271 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6272 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6273 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
6274 }
6275 else
6276 {
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05306277 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId,
6278 eCSR_SCAN_ABORT_DEFAULT);
Jeff Johnson295189b2012-06-20 16:38:30 -07006279 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306280#ifdef WLAN_NS_OFFLOAD
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306281#ifdef WLAN_OPEN_SOURCE
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306282 cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue);
6283#endif
Vinay Krishna Eranna941360f2014-01-16 15:38:22 +05306284 if (pAdapter->ipv6_notifier_registered)
6285 {
6286 hddLog(LOG1, FL("Unregistered IPv6 notifier"));
6287 unregister_inet6addr_notifier(&pAdapter->ipv6_notifier);
6288 pAdapter->ipv6_notifier_registered = false;
6289 }
Vinay Krishna Erannad5b2be22013-12-01 17:00:15 +05306290#endif
Vinay Krishna Erannad9cbdb32014-01-16 12:59:10 +05306291 if (pAdapter->ipv4_notifier_registered)
6292 {
6293 hddLog(LOG1, FL("Unregistered IPv4 notifier"));
6294 unregister_inetaddr_notifier(&pAdapter->ipv4_notifier);
6295 pAdapter->ipv4_notifier_registered = false;
6296 }
Vinay Krishna Eranna4d055d42013-12-17 17:02:01 +05306297#ifdef WLAN_OPEN_SOURCE
6298 cancel_work_sync(&pAdapter->ipv4NotifierWorkQueue);
6299#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006300 if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags))
6301 {
6302 INIT_COMPLETION(pAdapter->session_close_comp_var);
6303 if (eHAL_STATUS_SUCCESS ==
6304 sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId,
6305 hdd_smeCloseSessionCallback, pAdapter))
6306 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306307 unsigned long ret;
6308
Jeff Johnson295189b2012-06-20 16:38:30 -07006309 //Block on a completion variable. Can't wait forever though.
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306310 ret = wait_for_completion_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006311 &pAdapter->session_close_comp_var,
6312 msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306313 if ( 0 >= ret)
6314 {
6315 hddLog(LOGE, "%s: failure waiting for session_close_comp_var %ld",
6316 __func__, ret);
6317 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006318 }
6319 }
6320
6321 break;
6322
6323 case WLAN_HDD_SOFTAP:
6324 case WLAN_HDD_P2P_GO:
6325 //Any softap specific cleanup here...
6326 mutex_lock(&pHddCtx->sap_lock);
6327 if (test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6328 {
6329 VOS_STATUS status;
6330 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
6331
6332 //Stop Bss.
6333 status = WLANSAP_StopBss(pHddCtx->pvosContext);
6334 if (VOS_IS_STATUS_SUCCESS(status))
6335 {
6336 hdd_hostapd_state_t *pHostapdState =
6337 WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6338
6339 status = vos_wait_single_event(&pHostapdState->vosEvent, 10000);
6340
6341 if (!VOS_IS_STATUS_SUCCESS(status))
6342 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306343 hddLog(LOGE, "%s: failure waiting for WLANSAP_StopBss %d",
6344 __func__, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07006345 }
6346 }
6347 else
6348 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006349 hddLog(LOGE, "%s: failure in WLANSAP_StopBss", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006350 }
6351 clear_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags);
6352
6353 if (eHAL_STATUS_FAILURE ==
6354 ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG,
6355 0, NULL, eANI_BOOLEAN_FALSE))
6356 {
6357 hddLog(LOGE,
6358 "%s: Failed to set WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006359 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006360 }
6361
6362 if ( eHAL_STATUS_FAILURE == ccmCfgSetInt((WLAN_HDD_GET_CTX(pAdapter))->hHal,
6363 WNI_CFG_ASSOC_RSP_ADDNIE_FLAG, 0, NULL,
6364 eANI_BOOLEAN_FALSE) )
6365 {
6366 hddLog(LOGE,
6367 "Could not pass on WNI_CFG_ASSOC_RSP_ADDNIE_FLAG to CCM");
6368 }
6369
6370 // Reset WNI_CFG_PROBE_RSP Flags
6371 wlan_hdd_reset_prob_rspies(pAdapter);
6372 kfree(pAdapter->sessionCtx.ap.beacon);
6373 pAdapter->sessionCtx.ap.beacon = NULL;
6374 }
6375 mutex_unlock(&pHddCtx->sap_lock);
6376 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006377
Jeff Johnson295189b2012-06-20 16:38:30 -07006378 case WLAN_HDD_MONITOR:
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006379#ifdef WLAN_OPEN_SOURCE
6380 cancel_work_sync(&pAdapter->sessionCtx.monitor.pAdapterForTx->monTxWorkQueue);
6381#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07006382 break;
Sameer Thalappilbee426e2013-10-30 10:30:30 -07006383
Jeff Johnson295189b2012-06-20 16:38:30 -07006384 default:
6385 break;
6386 }
6387
6388 EXIT();
6389 return VOS_STATUS_SUCCESS;
6390}
6391
6392VOS_STATUS hdd_stop_all_adapters( hdd_context_t *pHddCtx )
6393{
6394 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6395 VOS_STATUS status;
6396 hdd_adapter_t *pAdapter;
6397
6398 ENTER();
6399
6400 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6401
6402 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6403 {
6404 pAdapter = pAdapterNode->pAdapter;
6405 netif_tx_disable(pAdapter->dev);
6406 netif_carrier_off(pAdapter->dev);
6407
6408 hdd_stop_adapter( pHddCtx, pAdapter );
6409
6410 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6411 pAdapterNode = pNext;
6412 }
6413
6414 EXIT();
6415
6416 return VOS_STATUS_SUCCESS;
6417}
6418
Rajeev Kumarf999e582014-01-09 17:33:29 -08006419
6420#ifdef FEATURE_WLAN_BATCH_SCAN
6421/**---------------------------------------------------------------------------
6422
6423 \brief hdd_deinit_batch_scan () - This function cleans up batch scan data
6424 structures
6425
6426 \param - pAdapter Pointer to HDD adapter
6427
6428 \return - None
6429
6430 --------------------------------------------------------------------------*/
6431void hdd_deinit_batch_scan(hdd_adapter_t *pAdapter)
6432{
6433 tHddBatchScanRsp *pNode;
6434 tHddBatchScanRsp *pPrev;
6435
6436 if (pAdapter)
6437 {
6438 pNode = pAdapter->pBatchScanRsp;
6439 while (pNode)
6440 {
6441 pPrev = pNode;
6442 pNode = pNode->pNext;
6443 vos_mem_free((v_VOID_t * )pPrev);
6444 }
6445 pAdapter->pBatchScanRsp = NULL;
6446 }
6447
6448 pAdapter->pBatchScanRsp = NULL;
6449 pAdapter->numScanList = 0;
6450 pAdapter->batchScanState = eHDD_BATCH_SCAN_STATE_STOPPED;
6451 pAdapter->prev_batch_id = 0;
6452
6453 return;
6454}
6455#endif
6456
6457
Jeff Johnson295189b2012-06-20 16:38:30 -07006458VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx )
6459{
6460 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6461 VOS_STATUS status;
6462 hdd_adapter_t *pAdapter;
6463
6464 ENTER();
6465
6466 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6467
6468 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6469 {
6470 pAdapter = pAdapterNode->pAdapter;
6471 netif_tx_disable(pAdapter->dev);
6472 netif_carrier_off(pAdapter->dev);
6473
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006474 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
6475
Jeff Johnson295189b2012-06-20 16:38:30 -07006476 hdd_deinit_tx_rx(pAdapter);
Madan Mohan Koyyalamudi8c6dec82013-09-26 15:56:13 +05306477 if (test_bit(WMM_INIT_DONE, &pAdapter->event_flags))
6478 {
6479 hdd_wmm_adapter_close( pAdapter );
6480 clear_bit(WMM_INIT_DONE, &pAdapter->event_flags);
6481 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006482
Rajeev Kumarf999e582014-01-09 17:33:29 -08006483#ifdef FEATURE_WLAN_BATCH_SCAN
6484 if (eHDD_BATCH_SCAN_STATE_STARTED == pAdapter->batchScanState)
6485 {
6486 hdd_deinit_batch_scan(pAdapter);
6487 }
6488#endif
6489
Jeff Johnson295189b2012-06-20 16:38:30 -07006490 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6491 pAdapterNode = pNext;
6492 }
6493
6494 EXIT();
6495
6496 return VOS_STATUS_SUCCESS;
6497}
6498
6499VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx )
6500{
6501 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6502 VOS_STATUS status;
6503 hdd_adapter_t *pAdapter;
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306504 eConnectionState connState;
Jeff Johnson295189b2012-06-20 16:38:30 -07006505
6506 ENTER();
6507
6508 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6509
6510 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6511 {
6512 pAdapter = pAdapterNode->pAdapter;
6513
6514 switch(pAdapter->device_mode)
6515 {
6516 case WLAN_HDD_INFRA_STATION:
6517 case WLAN_HDD_P2P_CLIENT:
Jeff Johnsone7245742012-09-05 17:12:55 -07006518 case WLAN_HDD_P2P_DEVICE:
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306519
6520 connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState;
6521
Jeff Johnson295189b2012-06-20 16:38:30 -07006522 hdd_init_station_mode(pAdapter);
6523 /* Open the gates for HDD to receive Wext commands */
6524 pAdapter->isLinkUpSvcNeeded = FALSE;
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07006525 pHddCtx->scan_info.mScanPending = FALSE;
6526 pHddCtx->scan_info.waitScanResult = FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006527
6528 //Trigger the initial scan
6529 hdd_wlan_initial_scan(pAdapter);
6530
6531 //Indicate disconnect event to supplicant if associated previously
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306532 if (eConnectionState_Associated == connState ||
6533 eConnectionState_IbssConnected == connState )
Jeff Johnson295189b2012-06-20 16:38:30 -07006534 {
6535 union iwreq_data wrqu;
6536 memset(&wrqu, '\0', sizeof(wrqu));
6537 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
6538 memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN);
6539 wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL);
Srinivas Girigowda66c05eb2013-07-14 13:06:01 -07006540 pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE;
Jeff Johnson295189b2012-06-20 16:38:30 -07006541
Jeff Johnson295189b2012-06-20 16:38:30 -07006542 /* indicate disconnected event to nl80211 */
6543 cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED,
6544 NULL, 0, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006545 }
Gopichand Nakkalaa3c8fb62013-06-21 15:36:42 +05306546 else if (eConnectionState_Connecting == connState)
6547 {
6548 /*
6549 * Indicate connect failure to supplicant if we were in the
6550 * process of connecting
6551 */
6552 cfg80211_connect_result(pAdapter->dev, NULL,
6553 NULL, 0, NULL, 0,
6554 WLAN_STATUS_ASSOC_DENIED_UNSPEC,
6555 GFP_KERNEL);
6556 }
Jeff Johnson295189b2012-06-20 16:38:30 -07006557 break;
6558
6559 case WLAN_HDD_SOFTAP:
6560 /* softAP can handle SSR */
6561 break;
6562
6563 case WLAN_HDD_P2P_GO:
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006564 hddLog(VOS_TRACE_LEVEL_ERROR, "%s [SSR] send stop ap to supplicant",
Jeff Johnson295189b2012-06-20 16:38:30 -07006565 __func__);
Sameer Thalappiledf0d792013-08-09 14:31:03 -07006566 cfg80211_ap_stopped(pAdapter->dev, GFP_KERNEL);
Jeff Johnson295189b2012-06-20 16:38:30 -07006567 break;
6568
6569 case WLAN_HDD_MONITOR:
6570 /* monitor interface start */
6571 break;
6572 default:
6573 break;
6574 }
6575
6576 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6577 pAdapterNode = pNext;
6578 }
6579
6580 EXIT();
6581
6582 return VOS_STATUS_SUCCESS;
6583}
6584
6585VOS_STATUS hdd_reconnect_all_adapters( hdd_context_t *pHddCtx )
6586{
6587 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6588 hdd_adapter_t *pAdapter;
6589 VOS_STATUS status;
6590 v_U32_t roamId;
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306591 long ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07006592
6593 ENTER();
6594
6595 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6596
6597 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6598 {
6599 pAdapter = pAdapterNode->pAdapter;
6600
6601 if( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ||
6602 (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
6603 {
6604 hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6605 hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
6606
6607 pHddStaCtx->conn_info.connState = eConnectionState_NotConnected;
6608 init_completion(&pAdapter->disconnect_comp_var);
6609 sme_RoamDisconnect(pHddCtx->hHal, pAdapter->sessionId,
6610 eCSR_DISCONNECT_REASON_UNSPECIFIED);
6611
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306612 ret = wait_for_completion_interruptible_timeout(
Jeff Johnson295189b2012-06-20 16:38:30 -07006613 &pAdapter->disconnect_comp_var,
6614 msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT));
c_hpothu6ff1c3c2013-10-01 19:01:57 +05306615 if (0 >= ret)
6616 hddLog(LOGE, "%s: failure waiting for disconnect_comp_var %ld",
6617 __func__, ret);
Jeff Johnson295189b2012-06-20 16:38:30 -07006618
6619 pWextState->roamProfile.csrPersona = pAdapter->device_mode;
6620 pHddCtx->isAmpAllowed = VOS_FALSE;
6621 sme_RoamConnect(pHddCtx->hHal,
6622 pAdapter->sessionId, &(pWextState->roamProfile),
6623 &roamId);
6624 }
6625
6626 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6627 pAdapterNode = pNext;
6628 }
6629
6630 EXIT();
6631
6632 return VOS_STATUS_SUCCESS;
6633}
6634
Sudhir Sattayappa Kohalli90e4c752013-03-21 14:25:04 -07006635void hdd_dump_concurrency_info(hdd_context_t *pHddCtx)
6636{
6637 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6638 VOS_STATUS status;
6639 hdd_adapter_t *pAdapter;
6640 hdd_station_ctx_t *pHddStaCtx;
6641 hdd_ap_ctx_t *pHddApCtx;
6642 hdd_hostapd_state_t * pHostapdState;
6643 tCsrBssid staBssid = { 0 }, p2pBssid = { 0 }, apBssid = { 0 };
6644 v_U8_t staChannel = 0, p2pChannel = 0, apChannel = 0;
6645 const char *p2pMode = "DEV";
6646 const char *ccMode = "Standalone";
6647 int n;
6648
6649 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6650 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6651 {
6652 pAdapter = pAdapterNode->pAdapter;
6653 switch (pAdapter->device_mode) {
6654 case WLAN_HDD_INFRA_STATION:
6655 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6656 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6657 staChannel = pHddStaCtx->conn_info.operationChannel;
6658 memcpy(staBssid, pHddStaCtx->conn_info.bssId, sizeof(staBssid));
6659 }
6660 break;
6661 case WLAN_HDD_P2P_CLIENT:
6662 pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter);
6663 if (eConnectionState_Associated == pHddStaCtx->conn_info.connState) {
6664 p2pChannel = pHddStaCtx->conn_info.operationChannel;
6665 memcpy(p2pBssid, pHddStaCtx->conn_info.bssId, sizeof(p2pBssid));
6666 p2pMode = "CLI";
6667 }
6668 break;
6669 case WLAN_HDD_P2P_GO:
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 p2pChannel = pHddApCtx->operatingChannel;
6674 memcpy(p2pBssid, pAdapter->macAddressCurrent.bytes, sizeof(p2pBssid));
6675 }
6676 p2pMode = "GO";
6677 break;
6678 case WLAN_HDD_SOFTAP:
6679 pHddApCtx = WLAN_HDD_GET_AP_CTX_PTR(pAdapter);
6680 pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter);
6681 if (pHostapdState->bssState == BSS_START && pHostapdState->vosStatus==VOS_STATUS_SUCCESS) {
6682 apChannel = pHddApCtx->operatingChannel;
6683 memcpy(apBssid, pAdapter->macAddressCurrent.bytes, sizeof(apBssid));
6684 }
6685 break;
6686 default:
6687 break;
6688 }
6689 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6690 pAdapterNode = pNext;
6691 }
6692 if (staChannel > 0 && (apChannel > 0 || p2pChannel > 0)) {
6693 ccMode = (p2pChannel==staChannel||apChannel==staChannel) ? "SCC" : "MCC";
6694 }
6695 n = pr_info("wlan(%d) " MAC_ADDRESS_STR " %s",
6696 staChannel, MAC_ADDR_ARRAY(staBssid), ccMode);
6697 if (p2pChannel > 0) {
6698 n += pr_info("p2p-%s(%d) " MAC_ADDRESS_STR,
6699 p2pMode, p2pChannel, MAC_ADDR_ARRAY(p2pBssid));
6700 }
6701 if (apChannel > 0) {
6702 n += pr_info("AP(%d) " MAC_ADDRESS_STR,
6703 apChannel, MAC_ADDR_ARRAY(apBssid));
6704 }
6705
6706 if (p2pChannel > 0 && apChannel > 0) {
6707 hddLog(VOS_TRACE_LEVEL_ERROR, "Error concurrent SAP %d and P2P %d which is not support", apChannel, p2pChannel);
6708 }
6709}
6710
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006711bool hdd_is_ssr_required( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07006712{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006713 return (isSsrRequired == HDD_SSR_REQUIRED);
Jeff Johnson295189b2012-06-20 16:38:30 -07006714}
6715
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006716/* Once SSR is disabled then it cannot be set. */
6717void hdd_set_ssr_required( e_hdd_ssr_required value)
Jeff Johnson295189b2012-06-20 16:38:30 -07006718{
Madan Mohan Koyyalamudib5da5332012-10-15 17:23:21 -07006719 if (HDD_SSR_DISABLED == isSsrRequired)
6720 return;
6721
Jeff Johnson295189b2012-06-20 16:38:30 -07006722 isSsrRequired = value;
6723}
6724
6725VOS_STATUS hdd_get_front_adapter( hdd_context_t *pHddCtx,
6726 hdd_adapter_list_node_t** ppAdapterNode)
6727{
6728 VOS_STATUS status;
6729 spin_lock(&pHddCtx->hddAdapters.lock);
6730 status = hdd_list_peek_front ( &pHddCtx->hddAdapters,
6731 (hdd_list_node_t**) ppAdapterNode );
6732 spin_unlock(&pHddCtx->hddAdapters.lock);
6733 return status;
6734}
6735
6736VOS_STATUS hdd_get_next_adapter( hdd_context_t *pHddCtx,
6737 hdd_adapter_list_node_t* pAdapterNode,
6738 hdd_adapter_list_node_t** pNextAdapterNode)
6739{
6740 VOS_STATUS status;
6741 spin_lock(&pHddCtx->hddAdapters.lock);
6742 status = hdd_list_peek_next ( &pHddCtx->hddAdapters,
6743 (hdd_list_node_t*) pAdapterNode,
6744 (hdd_list_node_t**)pNextAdapterNode );
6745
6746 spin_unlock(&pHddCtx->hddAdapters.lock);
6747 return status;
6748}
6749
6750VOS_STATUS hdd_remove_adapter( hdd_context_t *pHddCtx,
6751 hdd_adapter_list_node_t* pAdapterNode)
6752{
6753 VOS_STATUS status;
6754 spin_lock(&pHddCtx->hddAdapters.lock);
6755 status = hdd_list_remove_node ( &pHddCtx->hddAdapters,
6756 &pAdapterNode->node );
6757 spin_unlock(&pHddCtx->hddAdapters.lock);
6758 return status;
6759}
6760
6761VOS_STATUS hdd_remove_front_adapter( hdd_context_t *pHddCtx,
6762 hdd_adapter_list_node_t** ppAdapterNode)
6763{
6764 VOS_STATUS status;
6765 spin_lock(&pHddCtx->hddAdapters.lock);
6766 status = hdd_list_remove_front( &pHddCtx->hddAdapters,
6767 (hdd_list_node_t**) ppAdapterNode );
6768 spin_unlock(&pHddCtx->hddAdapters.lock);
6769 return status;
6770}
6771
6772VOS_STATUS hdd_add_adapter_back( hdd_context_t *pHddCtx,
6773 hdd_adapter_list_node_t* pAdapterNode)
6774{
6775 VOS_STATUS status;
6776 spin_lock(&pHddCtx->hddAdapters.lock);
6777 status = hdd_list_insert_back ( &pHddCtx->hddAdapters,
6778 (hdd_list_node_t*) pAdapterNode );
6779 spin_unlock(&pHddCtx->hddAdapters.lock);
6780 return status;
6781}
6782
6783VOS_STATUS hdd_add_adapter_front( hdd_context_t *pHddCtx,
6784 hdd_adapter_list_node_t* pAdapterNode)
6785{
6786 VOS_STATUS status;
6787 spin_lock(&pHddCtx->hddAdapters.lock);
6788 status = hdd_list_insert_front ( &pHddCtx->hddAdapters,
6789 (hdd_list_node_t*) pAdapterNode );
6790 spin_unlock(&pHddCtx->hddAdapters.lock);
6791 return status;
6792}
6793
6794hdd_adapter_t * hdd_get_adapter_by_macaddr( hdd_context_t *pHddCtx,
6795 tSirMacAddr macAddr )
6796{
6797 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6798 hdd_adapter_t *pAdapter;
6799 VOS_STATUS status;
6800
6801 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6802
6803 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6804 {
6805 pAdapter = pAdapterNode->pAdapter;
6806
6807 if( pAdapter && vos_mem_compare( pAdapter->macAddressCurrent.bytes,
6808 macAddr, sizeof(tSirMacAddr) ) )
6809 {
6810 return pAdapter;
6811 }
6812 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6813 pAdapterNode = pNext;
6814 }
6815
6816 return NULL;
6817
6818}
6819
6820hdd_adapter_t * hdd_get_adapter_by_name( hdd_context_t *pHddCtx, tANI_U8 *name )
6821{
6822 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6823 hdd_adapter_t *pAdapter;
6824 VOS_STATUS status;
6825
6826 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6827
6828 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6829 {
6830 pAdapter = pAdapterNode->pAdapter;
6831
6832 if( pAdapter && !strncmp( pAdapter->dev->name, (const char *)name,
6833 IFNAMSIZ ) )
6834 {
6835 return pAdapter;
6836 }
6837 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6838 pAdapterNode = pNext;
6839 }
6840
6841 return NULL;
6842
6843}
6844
6845hdd_adapter_t * hdd_get_adapter( hdd_context_t *pHddCtx, device_mode_t mode )
6846{
6847 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6848 hdd_adapter_t *pAdapter;
6849 VOS_STATUS status;
6850
6851 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6852
6853 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6854 {
6855 pAdapter = pAdapterNode->pAdapter;
6856
6857 if( pAdapter && (mode == pAdapter->device_mode) )
6858 {
6859 return pAdapter;
6860 }
6861 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6862 pAdapterNode = pNext;
6863 }
6864
6865 return NULL;
6866
6867}
6868
6869//Remove this function later
6870hdd_adapter_t * hdd_get_mon_adapter( hdd_context_t *pHddCtx )
6871{
6872 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6873 hdd_adapter_t *pAdapter;
6874 VOS_STATUS status;
6875
6876 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6877
6878 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6879 {
6880 pAdapter = pAdapterNode->pAdapter;
6881
6882 if( pAdapter && WLAN_HDD_MONITOR == pAdapter->device_mode )
6883 {
6884 return pAdapter;
6885 }
6886
6887 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6888 pAdapterNode = pNext;
6889 }
6890
6891 return NULL;
6892
6893}
6894
Jeff Johnson295189b2012-06-20 16:38:30 -07006895/**---------------------------------------------------------------------------
6896
6897 \brief hdd_set_monitor_tx_adapter() -
6898
6899 This API initializes the adapter to be used while transmitting on monitor
6900 adapter.
6901
6902 \param - pHddCtx - Pointer to the HDD context.
6903 pAdapter - Adapter that will used for TX. This can be NULL.
6904 \return - None.
6905 --------------------------------------------------------------------------*/
6906void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter )
6907{
6908 hdd_adapter_t *pMonAdapter;
6909
6910 pMonAdapter = hdd_get_adapter( pHddCtx, WLAN_HDD_MONITOR );
6911
6912 if( NULL != pMonAdapter )
6913 {
6914 pMonAdapter->sessionCtx.monitor.pAdapterForTx = pAdapter;
6915 }
6916}
Jeff Johnson295189b2012-06-20 16:38:30 -07006917/**---------------------------------------------------------------------------
6918
6919 \brief hdd_select_queue() -
6920
6921 This API returns the operating channel of the requested device mode
6922
6923 \param - pHddCtx - Pointer to the HDD context.
6924 - mode - Device mode for which operating channel is required
6925 suported modes - WLAN_HDD_INFRA_STATION, WLAN_HDD_P2P_CLIENT
6926 WLAN_HDD_SOFTAP, WLAN_HDD_P2P_GO.
6927 \return - channel number. "0" id the requested device is not found OR it is not connected.
6928 --------------------------------------------------------------------------*/
6929v_U8_t hdd_get_operating_channel( hdd_context_t *pHddCtx, device_mode_t mode )
6930{
6931 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
6932 VOS_STATUS status;
6933 hdd_adapter_t *pAdapter;
6934 v_U8_t operatingChannel = 0;
6935
6936 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
6937
6938 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
6939 {
6940 pAdapter = pAdapterNode->pAdapter;
6941
6942 if( mode == pAdapter->device_mode )
6943 {
6944 switch(pAdapter->device_mode)
6945 {
6946 case WLAN_HDD_INFRA_STATION:
6947 case WLAN_HDD_P2P_CLIENT:
6948 if( hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) )
6949 operatingChannel = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.operationChannel;
6950 break;
6951 case WLAN_HDD_SOFTAP:
6952 case WLAN_HDD_P2P_GO:
6953 /*softap connection info */
6954 if(test_bit(SOFTAP_BSS_STARTED, &pAdapter->event_flags))
6955 operatingChannel = (WLAN_HDD_GET_AP_CTX_PTR(pAdapter))->operatingChannel;
6956 break;
6957 default:
6958 break;
6959 }
6960
6961 break; //Found the device of interest. break the loop
6962 }
6963
6964 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
6965 pAdapterNode = pNext;
6966 }
6967 return operatingChannel;
6968}
6969
6970#ifdef WLAN_FEATURE_PACKET_FILTERING
6971/**---------------------------------------------------------------------------
6972
6973 \brief hdd_set_multicast_list() -
6974
6975 This used to set the multicast address list.
6976
6977 \param - dev - Pointer to the WLAN device.
6978 - skb - Pointer to OS packet (sk_buff).
6979 \return - success/fail
6980
6981 --------------------------------------------------------------------------*/
6982static void hdd_set_multicast_list(struct net_device *dev)
6983{
6984 hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev);
Jeff Johnson295189b2012-06-20 16:38:30 -07006985 int mc_count;
6986 int i = 0;
6987 struct netdev_hw_addr *ha;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306988
6989 if (NULL == pAdapter)
Jeff Johnson295189b2012-06-20 16:38:30 -07006990 {
6991 hddLog(VOS_TRACE_LEVEL_ERROR,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05306992 "%s: Adapter context is Null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07006993 return;
6994 }
6995
6996 if (dev->flags & IFF_ALLMULTI)
6997 {
6998 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07006999 "%s: allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307000 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007001 }
7002 else
7003 {
7004 mc_count = netdev_mc_count(dev);
7005 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007006 "%s: mc_count = %u", __func__, mc_count);
Jeff Johnson295189b2012-06-20 16:38:30 -07007007 if (mc_count > WLAN_HDD_MAX_MC_ADDR_LIST)
7008 {
7009 hddLog(VOS_TRACE_LEVEL_INFO,
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007010 "%s: No free filter available; allow all multicast frames", __func__);
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307011 pAdapter->mc_addr_list.mc_cnt = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07007012 return;
7013 }
7014
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307015 pAdapter->mc_addr_list.mc_cnt = mc_count;
Jeff Johnson295189b2012-06-20 16:38:30 -07007016
7017 netdev_for_each_mc_addr(ha, dev) {
7018 if (i == mc_count)
7019 break;
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307020 memset(&(pAdapter->mc_addr_list.addr[i][0]), 0, ETH_ALEN);
7021 memcpy(&(pAdapter->mc_addr_list.addr[i][0]), ha->addr, ETH_ALEN);
Arif Hussain6d2a3322013-11-17 19:50:10 -08007022 hddLog(VOS_TRACE_LEVEL_INFO, "%s: mlist[%d] = "MAC_ADDRESS_STR,
Jeff Johnson295189b2012-06-20 16:38:30 -07007023 __func__, i,
Gopichand Nakkala0f276812013-02-24 14:45:51 +05307024 MAC_ADDR_ARRAY(pAdapter->mc_addr_list.addr[i]));
Jeff Johnson295189b2012-06-20 16:38:30 -07007025 i++;
7026 }
7027 }
7028 return;
7029}
7030#endif
7031
7032/**---------------------------------------------------------------------------
7033
7034 \brief hdd_select_queue() -
7035
7036 This function is registered with the Linux OS for network
7037 core to decide which queue to use first.
7038
7039 \param - dev - Pointer to the WLAN device.
7040 - skb - Pointer to OS packet (sk_buff).
7041 \return - ac, Queue Index/access category corresponding to UP in IP header
7042
7043 --------------------------------------------------------------------------*/
7044v_U16_t hdd_select_queue(struct net_device *dev,
7045 struct sk_buff *skb)
7046{
7047 return hdd_wmm_select_queue(dev, skb);
7048}
7049
7050
7051/**---------------------------------------------------------------------------
7052
7053 \brief hdd_wlan_initial_scan() -
7054
7055 This function triggers the initial scan
7056
7057 \param - pAdapter - Pointer to the HDD adapter.
7058
7059 --------------------------------------------------------------------------*/
7060void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter)
7061{
7062 tCsrScanRequest scanReq;
7063 tCsrChannelInfo channelInfo;
7064 eHalStatus halStatus;
Jeff Johnson02797792013-10-26 19:17:13 -07007065 tANI_U32 scanId;
Jeff Johnson295189b2012-06-20 16:38:30 -07007066 hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
7067
7068 vos_mem_zero(&scanReq, sizeof(tCsrScanRequest));
7069 vos_mem_set(&scanReq.bssid, sizeof(tCsrBssid), 0xff);
7070 scanReq.BSSType = eCSR_BSS_TYPE_ANY;
7071
7072 if(sme_Is11dSupported(pHddCtx->hHal))
7073 {
7074 halStatus = sme_ScanGetBaseChannels( pHddCtx->hHal, &channelInfo );
7075 if ( HAL_STATUS_SUCCESS( halStatus ) )
7076 {
7077 scanReq.ChannelInfo.ChannelList = vos_mem_malloc(channelInfo.numOfChannels);
7078 if( !scanReq.ChannelInfo.ChannelList )
7079 {
7080 hddLog(VOS_TRACE_LEVEL_ERROR, "%s kmalloc failed", __func__);
7081 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007082 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007083 return;
7084 }
7085 vos_mem_copy(scanReq.ChannelInfo.ChannelList, channelInfo.ChannelList,
7086 channelInfo.numOfChannels);
7087 scanReq.ChannelInfo.numOfChannels = channelInfo.numOfChannels;
7088 vos_mem_free(channelInfo.ChannelList);
Srinivas Girigowda8d2348f2013-12-12 12:14:15 -08007089 channelInfo.ChannelList = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007090 }
7091
7092 scanReq.scanType = eSIR_PASSIVE_SCAN;
7093 scanReq.requestType = eCSR_SCAN_REQUEST_11D_SCAN;
7094 scanReq.maxChnTime = pHddCtx->cfg_ini->nPassiveMaxChnTime;
7095 scanReq.minChnTime = pHddCtx->cfg_ini->nPassiveMinChnTime;
7096 }
7097 else
7098 {
7099 scanReq.scanType = eSIR_ACTIVE_SCAN;
7100 scanReq.requestType = eCSR_SCAN_REQUEST_FULL_SCAN;
7101 scanReq.maxChnTime = pHddCtx->cfg_ini->nActiveMaxChnTime;
7102 scanReq.minChnTime = pHddCtx->cfg_ini->nActiveMinChnTime;
7103 }
7104
7105 halStatus = sme_ScanRequest(pHddCtx->hHal, pAdapter->sessionId, &scanReq, &scanId, NULL, NULL);
7106 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7107 {
7108 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_ScanRequest failed status code %d",
7109 __func__, halStatus );
7110 }
7111
7112 if(sme_Is11dSupported(pHddCtx->hHal))
7113 vos_mem_free(scanReq.ChannelInfo.ChannelList);
7114}
7115
Jeff Johnson295189b2012-06-20 16:38:30 -07007116/**---------------------------------------------------------------------------
7117
7118 \brief hdd_full_power_callback() - HDD full power callback function
7119
7120 This is the function invoked by SME to inform the result of a full power
7121 request issued by HDD
7122
7123 \param - callbackcontext - Pointer to cookie
7124 \param - status - result of request
7125
7126 \return - None
7127
7128 --------------------------------------------------------------------------*/
7129static void hdd_full_power_callback(void *callbackContext, eHalStatus status)
7130{
Jeff Johnson72a40512013-12-19 10:14:15 -08007131 struct statsContext *pContext = callbackContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007132
7133 hddLog(VOS_TRACE_LEVEL_INFO,
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307134 "%s: context = %p, status = %d", __func__, pContext, status);
Jeff Johnson295189b2012-06-20 16:38:30 -07007135
7136 if (NULL == callbackContext)
7137 {
7138 hddLog(VOS_TRACE_LEVEL_ERROR,
7139 "%s: Bad param, context [%p]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007140 __func__, callbackContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07007141 return;
7142 }
7143
Jeff Johnson72a40512013-12-19 10:14:15 -08007144 /* there is a race condition that exists between this callback
7145 function and the caller since the caller could time out either
7146 before or while this code is executing. we use a spinlock to
7147 serialize these actions */
7148 spin_lock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007149
7150 if (POWER_CONTEXT_MAGIC != pContext->magic)
7151 {
7152 /* the caller presumably timed out so there is nothing we can do */
Jeff Johnson72a40512013-12-19 10:14:15 -08007153 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007154 hddLog(VOS_TRACE_LEVEL_WARN,
7155 "%s: Invalid context, magic [%08x]",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007156 __func__, pContext->magic);
Jeff Johnson295189b2012-06-20 16:38:30 -07007157 return;
7158 }
7159
Jeff Johnson72a40512013-12-19 10:14:15 -08007160 /* context is valid so caller is still waiting */
7161
7162 /* paranoia: invalidate the magic */
7163 pContext->magic = 0;
7164
7165 /* notify the caller */
Jeff Johnson295189b2012-06-20 16:38:30 -07007166 complete(&pContext->completion);
Jeff Johnson72a40512013-12-19 10:14:15 -08007167
7168 /* serialization is complete */
7169 spin_unlock(&hdd_context_lock);
Jeff Johnson295189b2012-06-20 16:38:30 -07007170}
7171
7172/**---------------------------------------------------------------------------
7173
7174 \brief hdd_wlan_exit() - HDD WLAN exit function
7175
7176 This is the driver exit point (invoked during rmmod)
7177
7178 \param - pHddCtx - Pointer to the HDD Context
7179
7180 \return - None
7181
7182 --------------------------------------------------------------------------*/
7183void hdd_wlan_exit(hdd_context_t *pHddCtx)
7184{
7185 eHalStatus halStatus;
7186 v_CONTEXT_t pVosContext = pHddCtx->pvosContext;
7187 VOS_STATUS vosStatus;
Gopichand Nakkala66923aa2013-03-06 23:17:24 +05307188 struct wiphy *wiphy = pHddCtx->wiphy;
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007189 hdd_adapter_t* pAdapter = NULL;
Jeff Johnson72a40512013-12-19 10:14:15 -08007190 struct statsContext powerContext;
Jeff Johnson295189b2012-06-20 16:38:30 -07007191 long lrc;
7192
7193 ENTER();
7194
Jeff Johnson88ba7742013-02-27 14:36:02 -08007195 if (VOS_FTM_MODE != hdd_get_conparam())
7196 {
7197 // Unloading, restart logic is no more required.
7198 wlan_hdd_restart_deinit(pHddCtx);
7199 }
Jeff Johnsone7245742012-09-05 17:12:55 -07007200
Jeff Johnson295189b2012-06-20 16:38:30 -07007201 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007202 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007203 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007204 {
7205 hdd_adapter_t* pAdapter = hdd_get_adapter(pHddCtx,
7206 WLAN_HDD_INFRA_STATION);
7207 if (pAdapter == NULL)
7208 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_P2P_CLIENT);
7209
7210 if (pAdapter != NULL)
7211 {
7212 wlan_hdd_cfg80211_pre_voss_stop(pAdapter);
7213 hdd_UnregisterWext(pAdapter->dev);
7214 }
7215 }
7216 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007217
Jeff Johnson295189b2012-06-20 16:38:30 -07007218 if (VOS_FTM_MODE == hdd_get_conparam())
Jeff Johnson88ba7742013-02-27 14:36:02 -08007219 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307220 hddLog(VOS_TRACE_LEVEL_INFO,"%s: FTM MODE",__func__);
Jeff Johnson88ba7742013-02-27 14:36:02 -08007221 wlan_hdd_ftm_close(pHddCtx);
7222 goto free_hdd_ctx;
7223 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007224 //Stop the Interface TX queue.
7225 //netif_tx_disable(pWlanDev);
7226 //netif_carrier_off(pWlanDev);
7227
Jeff Johnson295189b2012-06-20 16:38:30 -07007228 if (VOS_STA_SAP_MODE == hdd_get_conparam())
7229 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307230 hddLog(VOS_TRACE_LEVEL_INFO,"%s: SAP MODE",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007231 pAdapter = hdd_get_adapter(pHddCtx,
7232 WLAN_HDD_SOFTAP);
7233 }
7234 else
7235 {
Jeff Johnson295189b2012-06-20 16:38:30 -07007236 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07007237 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307238 hddLog(VOS_TRACE_LEVEL_INFO,"%s: STA MODE",__func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007239 pAdapter = hdd_get_adapter(pHddCtx,
7240 WLAN_HDD_INFRA_STATION);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007241 if (pAdapter == NULL)
7242 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_IBSS);
Jeff Johnson295189b2012-06-20 16:38:30 -07007243 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007244 }
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307245
7246 if(NULL == pAdapter)
7247 {
7248 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: pAdapter is NULL",__func__);
7249 goto free_hdd_ctx;
7250 }
7251
Jeff Johnson295189b2012-06-20 16:38:30 -07007252 /* DeRegister with platform driver as client for Suspend/Resume */
7253 vosStatus = hddDeregisterPmOps(pHddCtx);
7254 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7255 {
7256 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDeregisterPmOps failed",__func__);
7257 VOS_ASSERT(0);
7258 }
7259
7260 vosStatus = hddDevTmUnregisterNotifyCallback(pHddCtx);
7261 if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) )
7262 {
7263 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmUnregisterNotifyCallback failed",__func__);
7264 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007265
7266 // Cancel any outstanding scan requests. We are about to close all
7267 // of our adapters, but an adapter structure is what SME passes back
7268 // to our callback function. Hence if there are any outstanding scan
7269 // requests then there is a race condition between when the adapter
7270 // is closed and when the callback is invoked. We try to resolve that
7271 // race condition here by canceling any outstanding scans before we
7272 // close the adapters.
7273 // Note that the scans may be cancelled in an asynchronous manner, so
7274 // ideally there needs to be some kind of synchronization. Rather than
7275 // introduce a new synchronization here, we will utilize the fact that
7276 // we are about to Request Full Power, and since that is synchronized,
7277 // the expectation is that by the time Request Full Power has completed,
7278 // all scans will be cancelled.
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007279 if (NULL != pAdapter)
Srinivas, Dasari138af4f2014-02-07 11:13:45 +05307280 hdd_abort_mac_scan(pHddCtx, pAdapter->sessionId, eCSR_SCAN_ABORT_DEFAULT);
Praveen Kumar Sirisilla47ce6ea2013-09-24 15:08:08 -07007281 else
7282 hddLog(VOS_TRACE_LEVEL_ERROR,
7283 "%s: pAdapter is NULL, cannot Abort scan", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07007284
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07007285 //Stop the traffic monitor timer
7286 if ( VOS_TIMER_STATE_RUNNING ==
7287 vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))
7288 {
7289 vos_timer_stop(&pHddCtx->tx_rx_trafficTmr);
7290 }
7291
7292 // Destroy the traffic monitor timer
7293 if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy(
7294 &pHddCtx->tx_rx_trafficTmr)))
7295 {
7296 hddLog(VOS_TRACE_LEVEL_ERROR,
7297 "%s: Cannot deallocate Traffic monitor timer", __func__);
7298 }
7299
Jeff Johnson295189b2012-06-20 16:38:30 -07007300 //Disable IMPS/BMPS as we do not want the device to enter any power
7301 //save mode during shutdown
7302 sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE);
7303 sme_DisablePowerSave(pHddCtx->hHal, ePMC_BEACON_MODE_POWER_SAVE);
7304 sme_DisablePowerSave(pHddCtx->hHal, ePMC_UAPSD_MODE_POWER_SAVE);
7305
7306 //Ensure that device is in full power as we will touch H/W during vos_Stop
7307 init_completion(&powerContext.completion);
7308 powerContext.magic = POWER_CONTEXT_MAGIC;
7309
7310 halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_full_power_callback,
7311 &powerContext, eSME_FULL_PWR_NEEDED_BY_HDD);
7312
7313 if (eHAL_STATUS_SUCCESS != halStatus)
7314 {
7315 if (eHAL_STATUS_PMC_PENDING == halStatus)
7316 {
7317 /* request was sent -- wait for the response */
7318 lrc = wait_for_completion_interruptible_timeout(
7319 &powerContext.completion,
7320 msecs_to_jiffies(WLAN_WAIT_TIME_POWER));
Jeff Johnson295189b2012-06-20 16:38:30 -07007321 if (lrc <= 0)
7322 {
7323 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: %s while requesting full power",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007324 __func__, (0 == lrc) ? "timeout" : "interrupt");
Jeff Johnson295189b2012-06-20 16:38:30 -07007325 }
7326 }
7327 else
7328 {
7329 hddLog(VOS_TRACE_LEVEL_ERROR,
7330 "%s: Request for Full Power failed, status %d",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007331 __func__, halStatus);
Jeff Johnson295189b2012-06-20 16:38:30 -07007332 /* continue -- need to clean up as much as possible */
7333 }
7334 }
7335
Jeff Johnson72a40512013-12-19 10:14:15 -08007336 /* either we never sent a request, we sent a request and received a
7337 response or we sent a request and timed out. if we never sent a
7338 request or if we sent a request and got a response, we want to
7339 clear the magic out of paranoia. if we timed out there is a
7340 race condition such that the callback function could be
7341 executing at the same time we are. of primary concern is if the
7342 callback function had already verified the "magic" but had not
7343 yet set the completion variable when a timeout occurred. we
7344 serialize these activities by invalidating the magic while
7345 holding a shared spinlock which will cause us to block if the
7346 callback is currently executing */
7347 spin_lock(&hdd_context_lock);
7348 powerContext.magic = 0;
7349 spin_unlock(&hdd_context_lock);
7350
Yue Ma0d4891e2013-08-06 17:01:45 -07007351 hdd_debugfs_exit(pHddCtx);
7352
Jeff Johnson295189b2012-06-20 16:38:30 -07007353 // Unregister the Net Device Notifier
7354 unregister_netdevice_notifier(&hdd_netdev_notifier);
7355
Jeff Johnson295189b2012-06-20 16:38:30 -07007356 hdd_stop_all_adapters( pHddCtx );
7357
Jeff Johnson295189b2012-06-20 16:38:30 -07007358#ifdef WLAN_BTAMP_FEATURE
7359 vosStatus = WLANBAP_Stop(pVosContext);
7360 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7361 {
7362 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7363 "%s: Failed to stop BAP",__func__);
7364 }
7365#endif //WLAN_BTAMP_FEATURE
7366
7367 //Stop all the modules
7368 vosStatus = vos_stop( pVosContext );
7369 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7370 {
7371 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
7372 "%s: Failed to stop VOSS",__func__);
7373 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7374 }
7375
Jeff Johnson295189b2012-06-20 16:38:30 -07007376 //Assert Deep sleep signal now to put Libra HW in lowest power state
7377 vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL );
7378 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7379
7380 //Vote off any PMIC voltage supplies
7381 vos_chipPowerDown(NULL, NULL, NULL);
7382
7383 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
7384
Leo Chang59cdc7e2013-07-10 10:08:21 -07007385
Jeff Johnson295189b2012-06-20 16:38:30 -07007386 //This requires pMac access, Call this before vos_close().
Jeff Johnson295189b2012-06-20 16:38:30 -07007387 hdd_unregister_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07007388
7389 //Close the scheduler before calling vos_close to make sure no thread is
7390 // scheduled after the each module close is called i.e after all the data
7391 // structures are freed.
7392 vosStatus = vos_sched_close( pVosContext );
7393 if (!VOS_IS_STATUS_SUCCESS(vosStatus)) {
7394 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
7395 "%s: Failed to close VOSS Scheduler",__func__);
7396 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7397 }
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007398#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07007399#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
7400 /* Destroy the wake lock */
7401 wake_lock_destroy(&pHddCtx->rx_wake_lock);
7402#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08007403 /* Destroy the wake lock */
7404 wake_lock_destroy(&pHddCtx->sap_wake_lock);
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007405#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007406
Mihir Shete7a24b5f2013-12-21 12:18:31 +05307407#ifdef CONFIG_ENABLE_LINUX_REG
7408 vosStatus = vos_nv_close();
7409 if (!VOS_IS_STATUS_SUCCESS(vosStatus))
7410 {
7411 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
7412 "%s: Failed to close NV", __func__);
7413 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) );
7414 }
7415#endif
7416
Jeff Johnson295189b2012-06-20 16:38:30 -07007417 //Close VOSS
7418 //This frees pMac(HAL) context. There should not be any call that requires pMac access after this.
7419 vos_close(pVosContext);
7420
Jeff Johnson295189b2012-06-20 16:38:30 -07007421 //Close Watchdog
7422 if(pHddCtx->cfg_ini->fIsLogpEnabled)
7423 vos_watchdog_close(pVosContext);
7424
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307425 //Clean up HDD Nlink Service
7426 send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0);
Leo Chang59cdc7e2013-07-10 10:08:21 -07007427#ifdef WLAN_KD_READY_NOTIFIER
7428 nl_srv_exit(pHddCtx->ptt_pid);
7429#else
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307430 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07007431#endif /* WLAN_KD_READY_NOTIFIER */
Gopichand Nakkalaa0358482013-06-12 17:05:47 +05307432
Jeff Johnson295189b2012-06-20 16:38:30 -07007433 /* Cancel the vote for XO Core ON.
7434 * This is done here to ensure there is no race condition since MC, TX and WD threads have
7435 * exited at this point
7436 */
7437 hddLog(VOS_TRACE_LEVEL_WARN, "In module exit: Cancel the vote for XO Core ON"
Arif Hussain6d2a3322013-11-17 19:50:10 -08007438 " when WLAN is turned OFF");
Jeff Johnson295189b2012-06-20 16:38:30 -07007439 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
7440 {
7441 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel the vote for XO Core ON."
7442 " Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08007443 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07007444 }
7445
7446 hdd_close_all_adapters( pHddCtx );
7447
7448
7449 //Free up dynamically allocated members inside HDD Adapter
7450 kfree(pHddCtx->cfg_ini);
7451 pHddCtx->cfg_ini= NULL;
7452
7453 /* free the power on lock from platform driver */
7454 if (free_riva_power_on_lock("wlan"))
7455 {
7456 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to free power on lock",
7457 __func__);
7458 }
7459
Jeff Johnson88ba7742013-02-27 14:36:02 -08007460free_hdd_ctx:
Leo Changf04ddad2013-09-18 13:46:38 -07007461 /* FTM mode, WIPHY did not registered
7462 If un-register here, system crash will happen */
7463 if (VOS_FTM_MODE != hdd_get_conparam())
7464 {
7465 wiphy_unregister(wiphy) ;
7466 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007467 wiphy_free(wiphy) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007468 if (hdd_is_ssr_required())
7469 {
7470 /* WDI timeout had happened during unload, so SSR is needed here */
Madan Mohan Koyyalamudi3246f5b2012-10-15 15:40:02 -07007471 subsystem_restart("wcnss");
Jeff Johnson295189b2012-06-20 16:38:30 -07007472 msleep(5000);
7473 }
7474 hdd_set_ssr_required (VOS_FALSE);
7475}
7476
7477
7478/**---------------------------------------------------------------------------
7479
7480 \brief hdd_update_config_from_nv() - Function to update the contents of
7481 the running configuration with parameters taken from NV storage
7482
7483 \param - pHddCtx - Pointer to the HDD global context
7484
7485 \return - VOS_STATUS_SUCCESS if successful
7486
7487 --------------------------------------------------------------------------*/
7488static VOS_STATUS hdd_update_config_from_nv(hdd_context_t* pHddCtx)
7489{
Jeff Johnson295189b2012-06-20 16:38:30 -07007490 v_BOOL_t itemIsValid = VOS_FALSE;
7491 VOS_STATUS status;
7492 v_MACADDR_t macFromNV[VOS_MAX_CONCURRENCY_PERSONA];
7493 v_U8_t macLoop;
7494
7495 /*If the NV is valid then get the macaddress from nv else get it from qcom_cfg.ini*/
7496 status = vos_nv_getValidity(VNV_FIELD_IMAGE, &itemIsValid);
7497 if(status != VOS_STATUS_SUCCESS)
7498 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007499 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_getValidity() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007500 return VOS_STATUS_E_FAILURE;
7501 }
7502
7503 if (itemIsValid == VOS_TRUE)
7504 {
Arif Hussain6d2a3322013-11-17 19:50:10 -08007505 hddLog(VOS_TRACE_LEVEL_INFO_HIGH," Reading the Macaddress from NV");
Jeff Johnson295189b2012-06-20 16:38:30 -07007506 status = vos_nv_readMultiMacAddress((v_U8_t *)&macFromNV[0].bytes[0],
7507 VOS_MAX_CONCURRENCY_PERSONA);
7508 if(status != VOS_STATUS_SUCCESS)
7509 {
7510 /* Get MAC from NV fail, not update CFG info
7511 * INI MAC value will be used for MAC setting */
Arif Hussain6d2a3322013-11-17 19:50:10 -08007512 hddLog(VOS_TRACE_LEVEL_ERROR," vos_nv_readMacAddress() failed");
Jeff Johnson295189b2012-06-20 16:38:30 -07007513 return VOS_STATUS_E_FAILURE;
7514 }
7515
7516 /* If first MAC is not valid, treat all others are not valid
7517 * Then all MACs will be got from ini file */
7518 if(vos_is_macaddr_zero(&macFromNV[0]))
7519 {
7520 /* MAC address in NV file is not configured yet */
7521 hddLog(VOS_TRACE_LEVEL_WARN, "Invalid MAC in NV file");
7522 return VOS_STATUS_E_INVAL;
7523 }
7524
7525 /* Get MAC address from NV, update CFG info */
7526 for(macLoop = 0; macLoop < VOS_MAX_CONCURRENCY_PERSONA; macLoop++)
7527 {
7528 if(vos_is_macaddr_zero(&macFromNV[macLoop]))
7529 {
c_hpothu6ff1c3c2013-10-01 19:01:57 +05307530 hddLog(VOS_TRACE_LEVEL_ERROR,"not valid MAC from NV for %d", macLoop);
Jeff Johnson295189b2012-06-20 16:38:30 -07007531 /* This MAC is not valid, skip it
7532 * This MAC will be got from ini file */
7533 }
7534 else
7535 {
7536 vos_mem_copy((v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[macLoop].bytes[0],
7537 (v_U8_t *)&macFromNV[macLoop].bytes[0],
7538 VOS_MAC_ADDR_SIZE);
7539 }
7540 }
7541 }
7542 else
7543 {
7544 hddLog(VOS_TRACE_LEVEL_ERROR, "NV ITEM, MAC Not valid");
7545 return VOS_STATUS_E_FAILURE;
7546 }
Jeff Johnson295189b2012-06-20 16:38:30 -07007547
Jeff Johnson295189b2012-06-20 16:38:30 -07007548
7549 return VOS_STATUS_SUCCESS;
7550}
7551
7552/**---------------------------------------------------------------------------
7553
7554 \brief hdd_post_voss_start_config() - HDD post voss start config helper
7555
7556 \param - pAdapter - Pointer to the HDD
7557
7558 \return - None
7559
7560 --------------------------------------------------------------------------*/
7561VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx)
7562{
7563 eHalStatus halStatus;
7564 v_U32_t listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307565 tANI_U32 ignoreDtim;
Jeff Johnson295189b2012-06-20 16:38:30 -07007566
Jeff Johnson295189b2012-06-20 16:38:30 -07007567
7568 // Send ready indication to the HDD. This will kick off the MAC
7569 // into a 'running' state and should kick off an initial scan.
7570 halStatus = sme_HDDReadyInd( pHddCtx->hHal );
7571 if ( !HAL_STATUS_SUCCESS( halStatus ) )
7572 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05307573 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status "
Jeff Johnson295189b2012-06-20 16:38:30 -07007574 "code %08d [x%08x]",__func__, halStatus, halStatus );
7575 return VOS_STATUS_E_FAILURE;
7576 }
7577
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307578 // Set default LI and ignoreDtim into HDD context,
Jeff Johnson295189b2012-06-20 16:38:30 -07007579 // otherwise under some race condition, HDD will set 0 LI value into RIVA,
7580 // And RIVA will crash
7581 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval);
7582 pHddCtx->hdd_actual_LI_value = listenInterval;
Gopichand Nakkalaa2fe5b02013-06-06 16:32:28 +05307583 wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim);
7584 pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim;
7585
7586
Jeff Johnson295189b2012-06-20 16:38:30 -07007587 return VOS_STATUS_SUCCESS;
7588}
7589
Jeff Johnson295189b2012-06-20 16:38:30 -07007590/* wake lock APIs for HDD */
7591void hdd_prevent_suspend(void)
7592{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007593#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007594 wake_lock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007595#else
7596 wcnss_prevent_suspend();
7597#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007598}
7599
7600void hdd_allow_suspend(void)
7601{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007602#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07007603 wake_unlock(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07007604#else
7605 wcnss_allow_suspend();
7606#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007607}
7608
Mahesh A Saptasagarb9c50402014-01-16 15:49:22 +05307609void hdd_prevent_suspend_timeout(v_U32_t timeout)
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007610{
Sameer Thalappil50dc0092013-02-19 17:23:33 -08007611#ifdef WLAN_OPEN_SOURCE
Amar Singhal6144c002013-05-03 16:11:42 -07007612 wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout));
Madan Mohan Koyyalamudi10d83a92012-09-28 15:47:05 -07007613#else
7614 /* Do nothing as there is no API in wcnss for timeout*/
7615#endif
7616}
7617
Jeff Johnson295189b2012-06-20 16:38:30 -07007618/**---------------------------------------------------------------------------
7619
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007620 \brief hdd_exchange_version_and_caps() - HDD function to exchange version and capability
7621 information between Host and Riva
7622
7623 This function gets reported version of FW
7624 It also finds the version of Riva headers used to compile the host
7625 It compares the above two and prints a warning if they are different
7626 It gets the SW and HW version string
7627 Finally, it exchanges capabilities between host and Riva i.e. host and riva exchange a msg
7628 indicating the features they support through a bitmap
7629
7630 \param - pHddCtx - Pointer to HDD context
7631
7632 \return - void
7633
7634 --------------------------------------------------------------------------*/
7635
7636void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx)
7637{
7638
7639 tSirVersionType versionCompiled;
7640 tSirVersionType versionReported;
7641 tSirVersionString versionString;
7642 tANI_U8 fwFeatCapsMsgSupported = 0;
7643 VOS_STATUS vstatus;
7644
Mingcheng Zhu87f22fc2014-01-30 19:23:32 -08007645 memset(&versionCompiled, 0, sizeof(versionCompiled));
7646 memset(&versionReported, 0, sizeof(versionReported));
7647
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007648 /* retrieve and display WCNSS version information */
7649 do {
7650
7651 vstatus = sme_GetWcnssWlanCompiledVersion(pHddCtx->hHal,
7652 &versionCompiled);
7653 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7654 {
7655 hddLog(VOS_TRACE_LEVEL_FATAL,
7656 "%s: unable to retrieve WCNSS WLAN compiled version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007657 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007658 break;
7659 }
7660
7661 vstatus = sme_GetWcnssWlanReportedVersion(pHddCtx->hHal,
7662 &versionReported);
7663 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7664 {
7665 hddLog(VOS_TRACE_LEVEL_FATAL,
7666 "%s: unable to retrieve WCNSS WLAN reported version",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007667 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007668 break;
7669 }
7670
7671 if ((versionCompiled.major != versionReported.major) ||
7672 (versionCompiled.minor != versionReported.minor) ||
7673 (versionCompiled.version != versionReported.version) ||
7674 (versionCompiled.revision != versionReported.revision))
7675 {
7676 pr_err("%s: WCNSS WLAN Version %u.%u.%u.%u, "
7677 "Host expected %u.%u.%u.%u\n",
7678 WLAN_MODULE_NAME,
7679 (int)versionReported.major,
7680 (int)versionReported.minor,
7681 (int)versionReported.version,
7682 (int)versionReported.revision,
7683 (int)versionCompiled.major,
7684 (int)versionCompiled.minor,
7685 (int)versionCompiled.version,
7686 (int)versionCompiled.revision);
7687 }
7688 else
7689 {
7690 pr_info("%s: WCNSS WLAN version %u.%u.%u.%u\n",
7691 WLAN_MODULE_NAME,
7692 (int)versionReported.major,
7693 (int)versionReported.minor,
7694 (int)versionReported.version,
7695 (int)versionReported.revision);
7696 }
7697
7698 vstatus = sme_GetWcnssSoftwareVersion(pHddCtx->hHal,
7699 versionString,
7700 sizeof(versionString));
7701 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7702 {
7703 hddLog(VOS_TRACE_LEVEL_FATAL,
7704 "%s: unable to retrieve WCNSS software version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007705 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007706 break;
7707 }
7708
7709 pr_info("%s: WCNSS software version %s\n",
7710 WLAN_MODULE_NAME, versionString);
7711
7712 vstatus = sme_GetWcnssHardwareVersion(pHddCtx->hHal,
7713 versionString,
7714 sizeof(versionString));
7715 if (!VOS_IS_STATUS_SUCCESS(vstatus))
7716 {
7717 hddLog(VOS_TRACE_LEVEL_FATAL,
7718 "%s: unable to retrieve WCNSS hardware version string",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07007719 __func__);
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007720 break;
7721 }
7722
7723 pr_info("%s: WCNSS hardware version %s\n",
7724 WLAN_MODULE_NAME, versionString);
7725
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007726 /* 1.Check if FW version is greater than 0.1.1.0. Only then send host-FW capability exchange message
7727 2.Host-FW capability exchange message is only present on riva 1.1 so
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007728 send the message only if it the riva is 1.1
7729 minor numbers for different riva branches:
7730 0 -> (1.0)Mainline Build
7731 1 -> (1.1)Mainline Build
7732 2->(1.04) Stability Build
7733 */
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007734 if (((versionReported.major>0) || (versionReported.minor>1) ||
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007735 ((versionReported.minor>=1) && (versionReported.version>=1)))
7736 && ((versionReported.major == 1) && (versionReported.minor >= 1)))
7737 fwFeatCapsMsgSupported = 1;
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07007738
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007739 if (fwFeatCapsMsgSupported)
Yathish9f22e662012-12-10 14:21:35 -08007740 {
7741#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
7742 if(!pHddCtx->cfg_ini->fEnableActiveModeOffload)
7743 sme_disableFeatureCapablity(WLANACTIVE_OFFLOAD);
7744#endif
Ravi Joshid2ca7c42013-07-23 08:37:49 -07007745 /* Indicate if IBSS heartbeat monitoring needs to be offloaded */
7746 if (!pHddCtx->cfg_ini->enableIbssHeartBeatOffload)
7747 {
7748 sme_disableFeatureCapablity(IBSS_HEARTBEAT_OFFLOAD);
7749 }
7750
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007751 sme_featureCapsExchange(pHddCtx->hHal);
Yathish9f22e662012-12-10 14:21:35 -08007752 }
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07007753
7754 } while (0);
7755
7756}
7757
7758/**---------------------------------------------------------------------------
7759
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307760 \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz
7761
7762 \param - pHddCtx - Pointer to the hdd context
7763
7764 \return - true if hardware supports 5GHz
7765
7766 --------------------------------------------------------------------------*/
7767static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx)
7768{
7769 /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1);
7770 * then hardware support 5Ghz.
7771 */
7772 if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode())
7773 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05307774 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware supports 5Ghz", __func__);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307775 return true;
7776 }
7777 else
7778 {
Agarwal Ashish971c2882013-10-30 20:11:12 +05307779 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Hardware doesn't supports 5Ghz",
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307780 __func__);
7781 return false;
7782 }
7783}
7784
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307785/**---------------------------------------------------------------------------
7786
7787 \brief hdd_generate_iface_mac_addr_auto() - HDD Mac Interface Auto
7788 generate function
7789
7790 This is generate the random mac address for WLAN interface
7791
7792 \param - pHddCtx - Pointer to HDD context
7793 idx - Start interface index to get auto
7794 generated mac addr.
7795 mac_addr - Mac address
7796
7797 \return - 0 for success, < 0 for failure
7798
7799 --------------------------------------------------------------------------*/
7800
7801static int hdd_generate_iface_mac_addr_auto(hdd_context_t *pHddCtx,
7802 int idx, v_MACADDR_t mac_addr)
7803{
7804 int i;
7805 unsigned int serialno;
7806 serialno = wcnss_get_serial_number();
7807
7808 if (0 != serialno)
7809 {
7810 /* MAC address has 3 bytes of OUI so we have a maximum of 3
7811 bytes of the serial number that can be used to generate
7812 the other 3 bytes of the MAC address. Mask off all but
7813 the lower 3 bytes (this will also make sure we don't
7814 overflow in the next step) */
7815 serialno &= 0x00FFFFFF;
7816
7817 /* we need a unique address for each session */
7818 serialno *= VOS_MAX_CONCURRENCY_PERSONA;
7819
7820 /* autogen other Mac addresses */
7821 for (i = idx; i < VOS_MAX_CONCURRENCY_PERSONA; i++)
7822 {
7823 /* start with the entire default address */
7824 pHddCtx->cfg_ini->intfMacAddr[i] = mac_addr;
7825 /* then replace the lower 3 bytes */
7826 pHddCtx->cfg_ini->intfMacAddr[i].bytes[3] = (serialno >> 16) & 0xFF;
7827 pHddCtx->cfg_ini->intfMacAddr[i].bytes[4] = (serialno >> 8) & 0xFF;
7828 pHddCtx->cfg_ini->intfMacAddr[i].bytes[5] = serialno & 0xFF;
7829
7830 serialno++;
7831 hddLog(VOS_TRACE_LEVEL_ERROR,
7832 "%s: Derived Mac Addr: "
7833 MAC_ADDRESS_STR, __func__,
7834 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[i].bytes));
7835 }
7836
7837 }
7838 else
7839 {
7840 hddLog(LOGE, FL("Failed to Get Serial NO"));
7841 return -1;
7842 }
7843 return 0;
7844}
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307845
7846/**---------------------------------------------------------------------------
7847
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05307848 \brief hdd_11d_scan_done - callback to be executed when 11d scan is
7849 completed to flush out the scan results
7850
7851 11d scan is done during driver load and is a passive scan on all
7852 channels supported by the device, 11d scans may find some APs on
7853 frequencies which are forbidden to be used in the regulatory domain
7854 the device is operating in. If these APs are notified to the supplicant
7855 it may try to connect to these APs, thus flush out all the scan results
7856 which are present in SME after 11d scan is done.
7857
7858 \return - eHalStatus
7859
7860 --------------------------------------------------------------------------*/
7861static eHalStatus hdd_11d_scan_done(tHalHandle halHandle, void *pContext,
7862 tANI_U32 scanId, eCsrScanStatus status)
7863{
7864 ENTER();
7865
7866 sme_ScanFlushResult(halHandle, 0);
7867
7868 EXIT();
7869
7870 return eHAL_STATUS_SUCCESS;
7871}
7872
7873/**---------------------------------------------------------------------------
7874
Jeff Johnson295189b2012-06-20 16:38:30 -07007875 \brief hdd_wlan_startup() - HDD init function
7876
7877 This is the driver startup code executed once a WLAN device has been detected
7878
7879 \param - dev - Pointer to the underlying device
7880
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007881 \return - 0 for success, < 0 for failure
Jeff Johnson295189b2012-06-20 16:38:30 -07007882
7883 --------------------------------------------------------------------------*/
7884
7885int hdd_wlan_startup(struct device *dev )
7886{
7887 VOS_STATUS status;
7888 hdd_adapter_t *pAdapter = NULL;
Jeff Johnsone7245742012-09-05 17:12:55 -07007889 hdd_adapter_t *pP2pAdapter = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07007890 hdd_context_t *pHddCtx = NULL;
7891 v_CONTEXT_t pVosContext= NULL;
7892#ifdef WLAN_BTAMP_FEATURE
7893 VOS_STATUS vStatus = VOS_STATUS_SUCCESS;
7894 WLANBAP_ConfigType btAmpConfig;
7895 hdd_config_t *pConfig;
7896#endif
7897 int ret;
Jeff Johnson295189b2012-06-20 16:38:30 -07007898 struct wiphy *wiphy;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05307899 v_MACADDR_t mac_addr;
Jeff Johnson295189b2012-06-20 16:38:30 -07007900
7901 ENTER();
Jeff Johnson295189b2012-06-20 16:38:30 -07007902 /*
7903 * cfg80211: wiphy allocation
7904 */
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05307905 wiphy = wlan_hdd_cfg80211_wiphy_alloc(sizeof(hdd_context_t)) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07007906
7907 if(wiphy == NULL)
7908 {
7909 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: cfg80211 init failed", __func__);
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08007910 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07007911 }
7912
7913 pHddCtx = wiphy_priv(wiphy);
7914
Jeff Johnson295189b2012-06-20 16:38:30 -07007915 //Initialize the adapter context to zeros.
7916 vos_mem_zero(pHddCtx, sizeof( hdd_context_t ));
7917
Jeff Johnson295189b2012-06-20 16:38:30 -07007918 pHddCtx->wiphy = wiphy;
Jeff Johnson295189b2012-06-20 16:38:30 -07007919 hdd_prevent_suspend();
7920 pHddCtx->isLoadUnloadInProgress = TRUE;
7921
7922 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
7923
7924 /*Get vos context here bcoz vos_open requires it*/
7925 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
7926
Madan Mohan Koyyalamudi0b78e152012-11-28 15:46:51 -08007927 if(pVosContext == NULL)
7928 {
7929 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed vos_get_global_context",__func__);
7930 goto err_free_hdd_context;
7931 }
7932
Jeff Johnson295189b2012-06-20 16:38:30 -07007933 //Save the Global VOSS context in adapter context for future.
7934 pHddCtx->pvosContext = pVosContext;
7935
7936 //Save the adapter context in global context for future.
7937 ((VosContextType*)(pVosContext))->pHDDContext = (v_VOID_t*)pHddCtx;
7938
Jeff Johnson295189b2012-06-20 16:38:30 -07007939 pHddCtx->parent_dev = dev;
7940
7941 init_completion(&pHddCtx->full_pwr_comp_var);
7942 init_completion(&pHddCtx->standby_comp_var);
7943 init_completion(&pHddCtx->req_bmps_comp_var);
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07007944 init_completion(&pHddCtx->scan_info.scan_req_completion_event);
Madan Mohan Koyyalamudif4e81002012-11-13 10:46:38 -08007945 init_completion(&pHddCtx->scan_info.abortscan_event_var);
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307946 init_completion(&pHddCtx->wiphy_channel_update_event);
Amar Singhala49cbc52013-10-08 18:37:44 -07007947
7948#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhalfddc28c2013-09-05 13:03:40 -07007949 init_completion(&pHddCtx->linux_reg_req);
Amar Singhala49cbc52013-10-08 18:37:44 -07007950#else
7951 init_completion(&pHddCtx->driver_crda_req);
7952#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007953
Kamath Vinayak4000c9a2013-08-23 14:24:27 +05307954 spin_lock_init(&pHddCtx->schedScan_lock);
7955
Jeff Johnson295189b2012-06-20 16:38:30 -07007956 hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS );
7957
Madan Mohan Koyyalamudi96797442013-10-08 16:04:42 +05307958#ifdef FEATURE_WLAN_TDLS
7959 /* tdls_lock is initialized before an hdd_open_adapter ( which is
7960 * invoked by other instances also) to protect the concurrent
7961 * access for the Adapters by TDLS module.
7962 */
7963 mutex_init(&pHddCtx->tdls_lock);
7964#endif
7965
Kiet Lam46b8e4e2013-11-06 21:49:53 +05307966 pHddCtx->nEnableStrictRegulatoryForFCC = TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07007967 // Load all config first as TL config is needed during vos_open
7968 pHddCtx->cfg_ini = (hdd_config_t*) kmalloc(sizeof(hdd_config_t), GFP_KERNEL);
7969 if(pHddCtx->cfg_ini == NULL)
7970 {
7971 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed kmalloc hdd_config_t",__func__);
7972 goto err_free_hdd_context;
7973 }
7974
7975 vos_mem_zero(pHddCtx->cfg_ini, sizeof( hdd_config_t ));
7976
7977 // Read and parse the qcom_cfg.ini file
7978 status = hdd_parse_config_ini( pHddCtx );
7979 if ( VOS_STATUS_SUCCESS != status )
7980 {
7981 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: error parsing %s",
7982 __func__, WLAN_INI_FILE);
7983 goto err_config;
7984 }
Arif Hussaind5218912013-12-05 01:10:55 -08007985#ifdef MEMORY_DEBUG
7986 if (pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled)
7987 vos_mem_init();
7988
7989 hddLog(VOS_TRACE_LEVEL_INFO, "%s: gEnableMemoryDebug=%d",
7990 __func__, pHddCtx->cfg_ini->IsMemoryDebugSupportEnabled);
7991#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07007992
Gopichand Nakkalab8f0f1a2013-05-23 18:19:48 +05307993 /* INI has been read, initialise the configuredMcastBcastFilter with
7994 * INI value as this will serve as the default value
7995 */
7996 pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting;
7997 hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d",
7998 pHddCtx->cfg_ini->mcastBcastFilterSetting);
Gopichand Nakkalafce506f2013-07-03 23:55:16 +05307999
8000 if (false == hdd_is_5g_supported(pHddCtx))
8001 {
8002 //5Ghz is not supported.
8003 if (1 != pHddCtx->cfg_ini->nBandCapability)
8004 {
8005 hddLog(VOS_TRACE_LEVEL_INFO,
8006 "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__);
8007 pHddCtx->cfg_ini->nBandCapability = 1;
8008 }
8009 }
Madan Mohan Koyyalamudid9383fd2013-08-13 09:27:30 +05308010
8011 /* If SNR Monitoring is enabled, FW has to parse all beacons
8012 * for calcaluting and storing the average SNR, so set Nth beacon
8013 * filter to 1 to enable FW to parse all the beaocons
8014 */
8015 if (1 == pHddCtx->cfg_ini->fEnableSNRMonitoring)
8016 {
8017 /* The log level is deliberately set to WARN as overriding
8018 * nthBeaconFilter to 1 will increase power cosumption and this
8019 * might just prove helpful to detect the power issue.
8020 */
8021 hddLog(VOS_TRACE_LEVEL_WARN,
8022 "%s: Setting pHddCtx->cfg_ini->nthBeaconFilter = 1", __func__);
8023 pHddCtx->cfg_ini->nthBeaconFilter = 1;
8024 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008025 /*
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308026 * cfg80211: Initialization ...
Jeff Johnson295189b2012-06-20 16:38:30 -07008027 */
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008028 if (VOS_FTM_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008029 {
Manjunathappa Prakasheec4ddf2014-01-13 18:23:51 -08008030 if (0 < wlan_hdd_cfg80211_init(dev, wiphy, pHddCtx->cfg_ini))
8031 {
8032 hddLog(VOS_TRACE_LEVEL_FATAL,
8033 "%s: wlan_hdd_cfg80211_init return failure", __func__);
8034 goto err_config;
8035 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008036 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008037
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008038 // Update VOS trace levels based upon the cfg.ini
8039 hdd_vos_trace_enable(VOS_MODULE_ID_BAP,
8040 pHddCtx->cfg_ini->vosTraceEnableBAP);
8041 hdd_vos_trace_enable(VOS_MODULE_ID_TL,
8042 pHddCtx->cfg_ini->vosTraceEnableTL);
8043 hdd_vos_trace_enable(VOS_MODULE_ID_WDI,
8044 pHddCtx->cfg_ini->vosTraceEnableWDI);
8045 hdd_vos_trace_enable(VOS_MODULE_ID_HDD,
8046 pHddCtx->cfg_ini->vosTraceEnableHDD);
8047 hdd_vos_trace_enable(VOS_MODULE_ID_SME,
8048 pHddCtx->cfg_ini->vosTraceEnableSME);
8049 hdd_vos_trace_enable(VOS_MODULE_ID_PE,
8050 pHddCtx->cfg_ini->vosTraceEnablePE);
Katya Nigam70d68332013-09-16 16:49:45 +05308051 hdd_vos_trace_enable(VOS_MODULE_ID_PMC,
8052 pHddCtx->cfg_ini->vosTraceEnablePMC);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008053 hdd_vos_trace_enable(VOS_MODULE_ID_WDA,
8054 pHddCtx->cfg_ini->vosTraceEnableWDA);
8055 hdd_vos_trace_enable(VOS_MODULE_ID_SYS,
8056 pHddCtx->cfg_ini->vosTraceEnableSYS);
8057 hdd_vos_trace_enable(VOS_MODULE_ID_VOSS,
8058 pHddCtx->cfg_ini->vosTraceEnableVOSS);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008059 hdd_vos_trace_enable(VOS_MODULE_ID_SAP,
8060 pHddCtx->cfg_ini->vosTraceEnableSAP);
8061 hdd_vos_trace_enable(VOS_MODULE_ID_HDD_SOFTAP,
8062 pHddCtx->cfg_ini->vosTraceEnableHDDSAP);
Varun Reddy Yeturu587e6802013-01-24 12:21:41 -08008063
Jeff Johnson295189b2012-06-20 16:38:30 -07008064 // Update WDI trace levels based upon the cfg.ini
8065 hdd_wdi_trace_enable(eWLAN_MODULE_DAL,
8066 pHddCtx->cfg_ini->wdiTraceEnableDAL);
8067 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_CTRL,
8068 pHddCtx->cfg_ini->wdiTraceEnableCTL);
8069 hdd_wdi_trace_enable(eWLAN_MODULE_DAL_DATA,
8070 pHddCtx->cfg_ini->wdiTraceEnableDAT);
8071 hdd_wdi_trace_enable(eWLAN_MODULE_PAL,
8072 pHddCtx->cfg_ini->wdiTraceEnablePAL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008073
Jeff Johnson88ba7742013-02-27 14:36:02 -08008074 if (VOS_FTM_MODE == hdd_get_conparam())
8075 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008076 if ( VOS_STATUS_SUCCESS != wlan_hdd_ftm_open(pHddCtx) )
8077 {
8078 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: wlan_hdd_ftm_open Failed",__func__);
8079 goto err_free_hdd_context;
8080 }
8081 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: FTM driver loaded success fully",__func__);
8082 return VOS_STATUS_SUCCESS;
Jeff Johnson88ba7742013-02-27 14:36:02 -08008083 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008084
Jeff Johnson88ba7742013-02-27 14:36:02 -08008085 //Open watchdog module
Jeff Johnson295189b2012-06-20 16:38:30 -07008086 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8087 {
8088 status = vos_watchdog_open(pVosContext,
8089 &((VosContextType*)pVosContext)->vosWatchdog, sizeof(VosWatchdogContext));
8090
8091 if(!VOS_IS_STATUS_SUCCESS( status ))
8092 {
8093 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_watchdog_open failed",__func__);
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308094 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008095 }
8096 }
8097
8098 pHddCtx->isLogpInProgress = FALSE;
8099 vos_set_logp_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8100
Jeff Johnson295189b2012-06-20 16:38:30 -07008101 status = vos_chipVoteOnXOBuffer(NULL, NULL, NULL);
8102 if(!VOS_IS_STATUS_SUCCESS(status))
8103 {
8104 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed to configure 19.2 MHz Clock", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008105 goto err_wdclose;
Jeff Johnson295189b2012-06-20 16:38:30 -07008106 }
8107
Amar Singhala49cbc52013-10-08 18:37:44 -07008108#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008109 /* initialize the NV module. This is required so that
8110 we can initialize the channel information in wiphy
8111 from the NV.bin data. The channel information in
8112 wiphy needs to be initialized before wiphy registration */
8113
8114 status = vos_nv_open();
8115 if (!VOS_IS_STATUS_SUCCESS(status))
8116 {
8117 /* NV module cannot be initialized */
8118 hddLog( VOS_TRACE_LEVEL_FATAL,
8119 "%s: vos_nv_open failed", __func__);
8120 goto err_clkvote;
8121 }
8122
8123 status = vos_init_wiphy_from_nv_bin();
8124 if (!VOS_IS_STATUS_SUCCESS(status))
8125 {
8126 /* NV module cannot be initialized */
8127 hddLog( VOS_TRACE_LEVEL_FATAL,
8128 "%s: vos_init_wiphy failed", __func__);
8129 goto err_vos_nv_close;
8130 }
8131
Amar Singhala49cbc52013-10-08 18:37:44 -07008132#endif
8133
Jeff Johnson295189b2012-06-20 16:38:30 -07008134 status = vos_open( &pVosContext, 0);
8135 if ( !VOS_IS_STATUS_SUCCESS( status ))
8136 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008137 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_open failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308138 goto err_vos_nv_close;
Jeff Johnson295189b2012-06-20 16:38:30 -07008139 }
8140
Jeff Johnson295189b2012-06-20 16:38:30 -07008141 pHddCtx->hHal = (tHalHandle)vos_get_context( VOS_MODULE_ID_SME, pVosContext );
8142
8143 if ( NULL == pHddCtx->hHal )
8144 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008145 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HAL context is null", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008146 goto err_vosclose;
8147 }
8148
Mihir Shetee1093ba2014-01-21 20:13:32 +05308149#ifdef CONFIG_ENABLE_LINUX_REG
8150 /* registration of wiphy dev with cfg80211 */
8151 if (0 > wlan_hdd_cfg80211_register(wiphy))
8152 {
8153 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8154 goto err_vosclose;
8155 }
8156
8157 status = wlan_hdd_init_channels(pHddCtx);
8158 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8159 {
8160 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: wlan_hdd_init_channels failed",
8161 __func__);
8162 goto err_wiphy_unregister;
8163 }
8164#endif
8165
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008166 status = vos_preStart( pHddCtx->pvosContext );
8167 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8168 {
8169 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: vos_preStart failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308170 goto err_wiphy_unregister;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008171 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008172
Arif Hussaineaf68602013-12-30 23:10:44 -08008173 if (0 == enable_dfs_chan_scan || 1 == enable_dfs_chan_scan)
8174 {
8175 pHddCtx->cfg_ini->enableDFSChnlScan = enable_dfs_chan_scan;
8176 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_dfs_chan_scan set to %d",
8177 __func__, enable_dfs_chan_scan);
8178 }
8179 if (0 == enable_11d || 1 == enable_11d)
8180 {
8181 pHddCtx->cfg_ini->Is11dSupportEnabled = enable_11d;
8182 hddLog(VOS_TRACE_LEVEL_INFO, "%s: module enable_11d set to %d",
8183 __func__, enable_11d);
8184 }
8185
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008186 /* Note that the vos_preStart() sequence triggers the cfg download.
8187 The cfg download must occur before we update the SME config
8188 since the SME config operation must access the cfg database */
Jeff Johnson295189b2012-06-20 16:38:30 -07008189 status = hdd_set_sme_config( pHddCtx );
8190
8191 if ( VOS_STATUS_SUCCESS != status )
8192 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008193 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Failed hdd_set_sme_config", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308194 goto err_wiphy_unregister;
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008195 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008196
8197 //Initialize the WMM module
8198 status = hdd_wmm_init(pHddCtx);
8199 if (!VOS_IS_STATUS_SUCCESS(status))
8200 {
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008201 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: hdd_wmm_init failed", __func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308202 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008203 }
8204
Jeff Johnson295189b2012-06-20 16:38:30 -07008205 /* In the integrated architecture we update the configuration from
8206 the INI file and from NV before vOSS has been started so that
8207 the final contents are available to send down to the cCPU */
8208
8209 // Apply the cfg.ini to cfg.dat
8210 if (FALSE == hdd_update_config_dat(pHddCtx))
8211 {
8212 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: config update failed",__func__ );
Mihir Shetee1093ba2014-01-21 20:13:32 +05308213 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008214 }
8215
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308216 // Get mac addr from platform driver
8217 ret = wcnss_get_wlan_mac_address((char*)&mac_addr.bytes);
8218
8219 if ((0 == ret) && (!vos_is_macaddr_zero(&mac_addr)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008220 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308221 /* Store the mac addr for first interface */
8222 pHddCtx->cfg_ini->intfMacAddr[0] = mac_addr;
8223
8224 hddLog(VOS_TRACE_LEVEL_ERROR,
8225 "%s: WLAN Mac Addr: "
8226 MAC_ADDRESS_STR, __func__,
8227 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8228
8229 /* Here, passing Arg2 as 1 because we do not want to change the
8230 last 3 bytes (means non OUI bytes) of first interface mac
8231 addr.
8232 */
8233 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 1, mac_addr))
8234 {
8235 hddLog(VOS_TRACE_LEVEL_ERROR,
8236 "%s: Failed to generate wlan interface mac addr "
8237 "using MAC from ini file ", __func__);
8238 }
8239 }
8240 else if (VOS_STATUS_SUCCESS != hdd_update_config_from_nv(pHddCtx))
8241 {
8242 // Apply the NV to cfg.dat
8243 /* Prima Update MAC address only at here */
Jeff Johnson295189b2012-06-20 16:38:30 -07008244#ifdef WLAN_AUTOGEN_MACADDR_FEATURE
8245 /* There was not a valid set of MAC Addresses in NV. See if the
8246 default addresses were modified by the cfg.ini settings. If so,
8247 we'll use them, but if not, we'll autogenerate a set of MAC
8248 addresses based upon the device serial number */
8249
8250 static const v_MACADDR_t default_address =
8251 {{0x00, 0x0A, 0xF5, 0x89, 0x89, 0xFF}};
Jeff Johnson295189b2012-06-20 16:38:30 -07008252
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308253 if (0 == memcmp(&default_address, &pHddCtx->cfg_ini->intfMacAddr[0],
8254 sizeof(default_address)))
Jeff Johnson295189b2012-06-20 16:38:30 -07008255 {
8256 /* cfg.ini has the default address, invoke autogen logic */
8257
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308258 /* Here, passing Arg2 as 0 because we want to change the
8259 last 3 bytes (means non OUI bytes) of all the interfaces
8260 mac addr.
8261 */
8262 if (0 != hdd_generate_iface_mac_addr_auto(pHddCtx, 0,
8263 default_address))
Jeff Johnson295189b2012-06-20 16:38:30 -07008264 {
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308265 hddLog(VOS_TRACE_LEVEL_ERROR,
8266 "%s: Failed to generate wlan interface mac addr "
8267 "using MAC from ini file " MAC_ADDRESS_STR, __func__,
8268 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
Jeff Johnson295189b2012-06-20 16:38:30 -07008269 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008270 }
8271 else
8272#endif //WLAN_AUTOGEN_MACADDR_FEATURE
8273 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008274 hddLog(VOS_TRACE_LEVEL_ERROR,
Jeff Johnson295189b2012-06-20 16:38:30 -07008275 "%s: Invalid MAC address in NV, using MAC from ini file "
8276 MAC_ADDRESS_STR, __func__,
8277 MAC_ADDR_ARRAY(pHddCtx->cfg_ini->intfMacAddr[0].bytes));
8278 }
8279 }
8280 {
8281 eHalStatus halStatus;
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308282
8283 /* Set the MAC Address Currently this is used by HAL to
8284 * add self sta. Remove this once self sta is added as
8285 * part of session open.
8286 */
Jeff Johnson295189b2012-06-20 16:38:30 -07008287 halStatus = cfgSetStr( pHddCtx->hHal, WNI_CFG_STA_ID,
8288 (v_U8_t *)&pHddCtx->cfg_ini->intfMacAddr[0],
8289 sizeof( pHddCtx->cfg_ini->intfMacAddr[0]) );
Hardik Kantilal Patel4d7982a2013-12-02 18:53:30 +05308290
Jeff Johnson295189b2012-06-20 16:38:30 -07008291 if (!HAL_STATUS_SUCCESS( halStatus ))
8292 {
8293 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: Failed to set MAC Address. "
8294 "HALStatus is %08d [x%08x]",__func__, halStatus, halStatus );
Mihir Shetee1093ba2014-01-21 20:13:32 +05308295 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008296 }
8297 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008298
8299 /*Start VOSS which starts up the SME/MAC/HAL modules and everything else
8300 Note: Firmware image will be read and downloaded inside vos_start API */
8301 status = vos_start( pHddCtx->pvosContext );
8302 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8303 {
8304 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_start failed",__func__);
Mihir Shetee1093ba2014-01-21 20:13:32 +05308305 goto err_wiphy_unregister;
Jeff Johnson295189b2012-06-20 16:38:30 -07008306 }
8307
Leo Chang6cec3e22014-01-21 15:33:49 -08008308#ifdef FEATURE_WLAN_CH_AVOID
8309 /* Plug in avoid channel notification callback
8310 * This should happen before ADD_SELF_STA
8311 * FW will send first IND with ADD_SELF_STA REQ from host */
8312 sme_AddChAvoidCallback(pHddCtx->hHal,
8313 hdd_hostapd_ch_avoid_cb);
8314#endif /* FEATURE_WLAN_CH_AVOID */
8315
Madan Mohan Koyyalamudi8612ec92012-09-28 15:53:07 -07008316 /* Exchange capability info between Host and FW and also get versioning info from FW */
8317 hdd_exchange_version_and_caps(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008318
8319 status = hdd_post_voss_start_config( pHddCtx );
8320 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8321 {
8322 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hdd_post_voss_start_config failed",
8323 __func__);
8324 goto err_vosstop;
8325 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008326
8327#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308328 wlan_hdd_cfg80211_update_reg_info( wiphy );
8329
8330 /* registration of wiphy dev with cfg80211 */
8331 if (0 > wlan_hdd_cfg80211_register(wiphy))
8332 {
8333 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy register failed", __func__);
8334 goto err_vosstop;
8335 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008336#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008337
Jeff Johnson295189b2012-06-20 16:38:30 -07008338 if (VOS_STA_SAP_MODE == hdd_get_conparam())
8339 {
8340 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_SOFTAP, "softap.%d",
8341 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8342 }
8343 else
8344 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008345 pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_INFRA_STATION, "wlan%d",
8346 wlan_hdd_get_intf_addr(pHddCtx), FALSE );
8347 if (pAdapter != NULL)
8348 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308349 if ( pHddCtx->cfg_ini->isP2pDeviceAddrAdministrated )
Jeff Johnson295189b2012-06-20 16:38:30 -07008350 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308351 vos_mem_copy( pHddCtx->p2pDeviceAddress.bytes,
8352 pHddCtx->cfg_ini->intfMacAddr[0].bytes,
8353 sizeof(tSirMacAddr));
Madan Mohan Koyyalamudiedfc1b72012-10-18 20:25:55 -07008354
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308355 /* Generate the P2P Device Address. This consists of the device's
8356 * primary MAC address with the locally administered bit set.
8357 */
8358 pHddCtx->p2pDeviceAddress.bytes[0] |= 0x02;
Jeff Johnsone7245742012-09-05 17:12:55 -07008359 }
8360 else
8361 {
Gopichand Nakkala49f96f62013-02-06 14:38:17 +05308362 tANI_U8* p2p_dev_addr = wlan_hdd_get_intf_addr(pHddCtx);
8363 if (p2p_dev_addr != NULL)
8364 {
8365 vos_mem_copy(&pHddCtx->p2pDeviceAddress.bytes[0],
8366 p2p_dev_addr, VOS_MAC_ADDR_SIZE);
8367 }
8368 else
8369 {
8370 hddLog(VOS_TRACE_LEVEL_FATAL,
8371 "%s: Failed to allocate mac_address for p2p_device",
8372 __func__);
8373 goto err_close_adapter;
8374 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008375 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008376
8377 pP2pAdapter = hdd_open_adapter( pHddCtx, WLAN_HDD_P2P_DEVICE, "p2p%d",
8378 &pHddCtx->p2pDeviceAddress.bytes[0], FALSE );
8379 if ( NULL == pP2pAdapter )
8380 {
8381 hddLog(VOS_TRACE_LEVEL_FATAL,
8382 "%s: Failed to do hdd_open_adapter for P2P Device Interface",
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07008383 __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008384 goto err_close_adapter;
8385 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008386 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008387 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008388
8389 if( pAdapter == NULL )
8390 {
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008391 hddLog(VOS_TRACE_LEVEL_ERROR, "%s: hdd_open_adapter failed", __func__);
8392 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008393 }
Jeff Johnsone7245742012-09-05 17:12:55 -07008394
Arif Hussain66559122013-11-21 10:11:40 -08008395 if (country_code)
8396 {
8397 eHalStatus ret;
Arif Hussaincb607082013-12-20 11:57:42 -08008398 INIT_COMPLETION(pAdapter->change_country_code);
Arif Hussain66559122013-11-21 10:11:40 -08008399 hdd_checkandupdate_dfssetting(pAdapter, country_code);
8400#ifndef CONFIG_ENABLE_LINUX_REG
8401 hdd_checkandupdate_phymode(pAdapter, country_code);
8402#endif
Arif Hussaineaf68602013-12-30 23:10:44 -08008403 ret = sme_ChangeCountryCode(pHddCtx->hHal,
8404 (void *)(tSmeChangeCountryCallback)
8405 wlan_hdd_change_country_code_callback,
Arif Hussain66559122013-11-21 10:11:40 -08008406 country_code,
8407 pAdapter, pHddCtx->pvosContext,
Abhishek Singha306a442013-11-07 18:39:01 +05308408 eSIR_TRUE, eSIR_TRUE);
Arif Hussain66559122013-11-21 10:11:40 -08008409 if (eHAL_STATUS_SUCCESS == ret)
8410 {
Arif Hussaincb607082013-12-20 11:57:42 -08008411 ret = wait_for_completion_interruptible_timeout(
8412 &pAdapter->change_country_code,
8413 msecs_to_jiffies(WLAN_WAIT_TIME_COUNTRY));
8414
8415 if (0 >= ret)
8416 {
8417 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8418 "%s: SME while setting country code timed out", __func__);
8419 }
Arif Hussain66559122013-11-21 10:11:40 -08008420 }
8421 else
8422 {
Arif Hussaincb607082013-12-20 11:57:42 -08008423 VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8424 "%s: SME Change Country code from module param fail ret=%d",
8425 __func__, ret);
Arif Hussain66559122013-11-21 10:11:40 -08008426 }
8427 }
8428
Jeff Johnson295189b2012-06-20 16:38:30 -07008429#ifdef WLAN_BTAMP_FEATURE
8430 vStatus = WLANBAP_Open(pVosContext);
8431 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8432 {
8433 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8434 "%s: Failed to open BAP",__func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008435 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008436 }
8437
8438 vStatus = BSL_Init(pVosContext);
8439 if(!VOS_IS_STATUS_SUCCESS(vStatus))
8440 {
8441 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8442 "%s: Failed to Init BSL",__func__);
8443 goto err_bap_close;
8444 }
8445 vStatus = WLANBAP_Start(pVosContext);
8446 if (!VOS_IS_STATUS_SUCCESS(vStatus))
8447 {
8448 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8449 "%s: Failed to start TL",__func__);
8450 goto err_bap_close;
8451 }
8452
8453 pConfig = pHddCtx->cfg_ini;
8454 btAmpConfig.ucPreferredChannel = pConfig->preferredChannel;
8455 status = WLANBAP_SetConfig(&btAmpConfig);
8456
8457#endif //WLAN_BTAMP_FEATURE
Jeff Johnsone7245742012-09-05 17:12:55 -07008458
Varun Reddy Yeturud0a3f252013-04-15 21:58:13 -07008459#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD
8460 if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE))
8461 {
8462 hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__);
8463 pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0;
8464 sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal),
8465 pHddCtx->cfg_ini->isRoamOffloadScanEnabled);
8466 }
8467#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008468#ifdef FEATURE_WLAN_SCAN_PNO
8469 /*SME must send channel update configuration to RIVA*/
8470 sme_UpdateChannelConfig(pHddCtx->hHal);
8471#endif
8472
Mihir Shetefc7ff5b2014-01-27 11:30:05 +05308473 sme_Register11dScanDoneCallback(pHddCtx->hHal, hdd_11d_scan_done);
8474
Jeff Johnson295189b2012-06-20 16:38:30 -07008475 /* Register with platform driver as client for Suspend/Resume */
8476 status = hddRegisterPmOps(pHddCtx);
8477 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8478 {
8479 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddRegisterPmOps failed",__func__);
8480#ifdef WLAN_BTAMP_FEATURE
8481 goto err_bap_stop;
8482#else
Jeff Johnsone7245742012-09-05 17:12:55 -07008483 goto err_close_adapter;
Jeff Johnson295189b2012-06-20 16:38:30 -07008484#endif //WLAN_BTAMP_FEATURE
8485 }
8486
Yue Ma0d4891e2013-08-06 17:01:45 -07008487 /* Open debugfs interface */
8488 if (VOS_STATUS_SUCCESS != hdd_debugfs_init(pAdapter))
8489 {
8490 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR,
8491 "%s: hdd_debugfs_init failed!", __func__);
Yue Ma0d4891e2013-08-06 17:01:45 -07008492 }
8493
Jeff Johnson295189b2012-06-20 16:38:30 -07008494 /* Register TM level change handler function to the platform */
8495 status = hddDevTmRegisterNotifyCallback(pHddCtx);
8496 if ( !VOS_IS_STATUS_SUCCESS( status ) )
8497 {
8498 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: hddDevTmRegisterNotifyCallback failed",__func__);
8499 goto err_unregister_pmops;
8500 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008501
8502 /* register for riva power on lock to platform driver */
8503 if (req_riva_power_on_lock("wlan"))
8504 {
8505 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: req riva power on lock failed",
8506 __func__);
8507 goto err_unregister_pmops;
8508 }
8509
Jeff Johnson295189b2012-06-20 16:38:30 -07008510 // register net device notifier for device change notification
8511 ret = register_netdevice_notifier(&hdd_netdev_notifier);
8512
8513 if(ret < 0)
8514 {
8515 hddLog(VOS_TRACE_LEVEL_ERROR,"%s: register_netdevice_notifier failed",__func__);
8516 goto err_free_power_on_lock;
8517 }
8518
8519 //Initialize the nlink service
8520 if(nl_srv_init() != 0)
8521 {
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05308522 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008523 goto err_reg_netdev;
8524 }
8525
Leo Chang4ce1cc52013-10-21 18:27:15 -07008526#ifdef WLAN_KD_READY_NOTIFIER
8527 pHddCtx->kd_nl_init = 1;
8528#endif /* WLAN_KD_READY_NOTIFIER */
8529
Jeff Johnson295189b2012-06-20 16:38:30 -07008530 //Initialize the BTC service
8531 if(btc_activate_service(pHddCtx) != 0)
8532 {
8533 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: btc_activate_service failed",__func__);
8534 goto err_nl_srv;
8535 }
8536
8537#ifdef PTT_SOCK_SVC_ENABLE
8538 //Initialize the PTT service
8539 if(ptt_sock_activate_svc(pHddCtx) != 0)
8540 {
8541 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: ptt_sock_activate_svc failed",__func__);
8542 goto err_nl_srv;
8543 }
8544#endif
8545
Jeff Johnson295189b2012-06-20 16:38:30 -07008546 hdd_register_mcast_bcast_filter(pHddCtx);
Jeff Johnson295189b2012-06-20 16:38:30 -07008547 if (VOS_STA_SAP_MODE != hdd_get_conparam())
Jeff Johnson295189b2012-06-20 16:38:30 -07008548 {
Madan Mohan Koyyalamudic537df22012-10-22 15:07:08 -07008549 /* Action frame registered in one adapter which will
8550 * applicable to all interfaces
8551 */
Madan Mohan Koyyalamudie233e292012-09-18 17:38:02 -07008552 wlan_hdd_cfg80211_post_voss_start(pAdapter);
Jeff Johnson295189b2012-06-20 16:38:30 -07008553 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008554
8555 mutex_init(&pHddCtx->sap_lock);
8556
8557 pHddCtx->isLoadUnloadInProgress = FALSE;
8558
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008559#ifdef WLAN_OPEN_SOURCE
Jeff Johnsone7245742012-09-05 17:12:55 -07008560#ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK
8561 /* Initialize the wake lcok */
8562 wake_lock_init(&pHddCtx->rx_wake_lock,
8563 WAKE_LOCK_SUSPEND,
8564 "qcom_rx_wakelock");
8565#endif
Madan Mohan Koyyalamudi69fc3ad2012-11-28 16:04:56 -08008566 /* Initialize the wake lcok */
8567 wake_lock_init(&pHddCtx->sap_wake_lock,
8568 WAKE_LOCK_SUSPEND,
8569 "qcom_sap_wakelock");
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008570#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008571
Madan Mohan Koyyalamudi2a1ba772012-10-11 14:59:06 -07008572 vos_event_init(&pHddCtx->scan_info.scan_finished_event);
8573 pHddCtx->scan_info.scan_pending_option = WEXT_SCAN_PENDING_GIVEUP;
Jeff Johnson295189b2012-06-20 16:38:30 -07008574
8575 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, FALSE);
8576 hdd_allow_suspend();
Abhishek Singha306a442013-11-07 18:39:01 +05308577#ifndef CONFIG_ENABLE_LINUX_REG
8578 /*updating wiphy so that regulatory user hints can be processed*/
8579 if (wiphy)
8580 {
8581 regulatory_hint(wiphy, "00");
8582 }
8583#endif
Jeff Johnsone7245742012-09-05 17:12:55 -07008584 // Initialize the restart logic
8585 wlan_hdd_restart_init(pHddCtx);
Chilam NG571c65a2013-01-19 12:27:36 +05308586
Sudhir Sattayappa Kohalli37620692013-08-05 14:02:26 -07008587 //Register the traffic monitor timer now
8588 if ( pHddCtx->cfg_ini->dynSplitscan)
8589 {
8590 vos_timer_init(&pHddCtx->tx_rx_trafficTmr,
8591 VOS_TIMER_TYPE_SW,
8592 hdd_tx_rx_pkt_cnt_stat_timer_handler,
8593 (void *)pHddCtx);
8594 }
Jeff Johnson295189b2012-06-20 16:38:30 -07008595 goto success;
8596
8597err_nl_srv:
Leo Chang59cdc7e2013-07-10 10:08:21 -07008598#ifdef WLAN_KD_READY_NOTIFIER
8599 nl_srv_exit(pHddCtx->ptt_pid);
8600#else
Jeff Johnson295189b2012-06-20 16:38:30 -07008601 nl_srv_exit();
Leo Chang59cdc7e2013-07-10 10:08:21 -07008602#endif /* WLAN_KD_READY_NOTIFIER */
Jeff Johnson295189b2012-06-20 16:38:30 -07008603err_reg_netdev:
8604 unregister_netdevice_notifier(&hdd_netdev_notifier);
8605
8606err_free_power_on_lock:
8607 free_riva_power_on_lock("wlan");
8608
8609err_unregister_pmops:
8610 hddDevTmUnregisterNotifyCallback(pHddCtx);
8611 hddDeregisterPmOps(pHddCtx);
8612
Yue Ma0d4891e2013-08-06 17:01:45 -07008613 hdd_debugfs_exit(pHddCtx);
8614
Jeff Johnson295189b2012-06-20 16:38:30 -07008615#ifdef WLAN_BTAMP_FEATURE
8616err_bap_stop:
8617 WLANBAP_Stop(pVosContext);
8618#endif
8619
8620#ifdef WLAN_BTAMP_FEATURE
8621err_bap_close:
8622 WLANBAP_Close(pVosContext);
8623#endif
8624
Jeff Johnson295189b2012-06-20 16:38:30 -07008625err_close_adapter:
8626 hdd_close_all_adapters( pHddCtx );
Amar Singhala49cbc52013-10-08 18:37:44 -07008627
8628#ifndef CONFIG_ENABLE_LINUX_REG
Madan Mohan Koyyalamudi71278262013-04-12 22:00:48 +05308629 wiphy_unregister(wiphy) ;
Amar Singhala49cbc52013-10-08 18:37:44 -07008630#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008631
8632err_vosstop:
8633 vos_stop(pVosContext);
8634
Mihir Shetee1093ba2014-01-21 20:13:32 +05308635err_wiphy_unregister:
8636#ifdef CONFIG_ENABLE_LINUX_REG
8637 wiphy_unregister(wiphy);
8638#endif
8639
Amar Singhala49cbc52013-10-08 18:37:44 -07008640err_vosclose:
Jeff Johnson295189b2012-06-20 16:38:30 -07008641 status = vos_sched_close( pVosContext );
8642 if (!VOS_IS_STATUS_SUCCESS(status)) {
8643 VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_FATAL,
8644 "%s: Failed to close VOSS Scheduler", __func__);
8645 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status ) );
8646 }
Amar Singhala49cbc52013-10-08 18:37:44 -07008647 vos_close(pVosContext );
8648
Amar Singhala49cbc52013-10-08 18:37:44 -07008649#ifdef CONFIG_ENABLE_LINUX_REG
Amar Singhal0a402232013-10-11 20:57:16 -07008650err_vos_nv_close:
8651
8652 vos_nv_close();
8653
Jeff Johnson295189b2012-06-20 16:38:30 -07008654err_clkvote:
Amar Singhala49cbc52013-10-08 18:37:44 -07008655#endif
8656
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008657 vos_chipVoteOffXOBuffer(NULL, NULL, NULL);
Jeff Johnson295189b2012-06-20 16:38:30 -07008658
8659err_wdclose:
8660 if(pHddCtx->cfg_ini->fIsLogpEnabled)
8661 vos_watchdog_close(pVosContext);
8662
Jeff Johnson295189b2012-06-20 16:38:30 -07008663err_config:
8664 kfree(pHddCtx->cfg_ini);
8665 pHddCtx->cfg_ini= NULL;
8666
8667err_free_hdd_context:
8668 hdd_allow_suspend();
Jeff Johnson295189b2012-06-20 16:38:30 -07008669 wiphy_free(wiphy) ;
8670 //kfree(wdev) ;
Jeff Johnson295189b2012-06-20 16:38:30 -07008671 VOS_BUG(1);
8672
Madan Mohan Koyyalamudid57ae632012-11-06 18:42:48 -08008673 if (hdd_is_ssr_required())
8674 {
8675 /* WDI timeout had happened during load, so SSR is needed here */
8676 subsystem_restart("wcnss");
8677 msleep(5000);
8678 }
8679 hdd_set_ssr_required (VOS_FALSE);
8680
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008681 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008682
8683success:
8684 EXIT();
8685 return 0;
8686}
8687
8688/**---------------------------------------------------------------------------
8689
Jeff Johnson32d95a32012-09-10 13:15:23 -07008690 \brief hdd_driver_init() - Core Driver Init Function
Jeff Johnson295189b2012-06-20 16:38:30 -07008691
Jeff Johnson32d95a32012-09-10 13:15:23 -07008692 This is the driver entry point - called in different timeline depending
8693 on whether the driver is statically or dynamically linked
Jeff Johnson295189b2012-06-20 16:38:30 -07008694
8695 \param - None
8696
8697 \return - 0 for success, non zero for failure
8698
8699 --------------------------------------------------------------------------*/
Jeff Johnson32d95a32012-09-10 13:15:23 -07008700static int hdd_driver_init( void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008701{
8702 VOS_STATUS status;
8703 v_CONTEXT_t pVosContext = NULL;
Jeff Johnson295189b2012-06-20 16:38:30 -07008704 struct device *dev = NULL;
8705 int ret_status = 0;
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008706#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8707 int max_retries = 0;
8708#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008709
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308710#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8711 vos_wconn_trace_init();
8712#endif
8713
Jeff Johnson295189b2012-06-20 16:38:30 -07008714 ENTER();
8715
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008716#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008717 wake_lock_init(&wlan_wake_lock, WAKE_LOCK_SUSPEND, "wlan");
Jeff Johnsone7245742012-09-05 17:12:55 -07008718#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008719
8720 pr_info("%s: loading driver v%s\n", WLAN_MODULE_NAME,
8721 QWLAN_VERSIONSTR TIMER_MANAGER_STR MEMORY_DEBUG_STR);
8722
8723 //Power Up Libra WLAN card first if not already powered up
8724 status = vos_chipPowerUp(NULL,NULL,NULL);
8725 if (!VOS_IS_STATUS_SUCCESS(status))
8726 {
8727 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. "
8728 "exiting", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308729#ifdef WLAN_OPEN_SOURCE
8730 wake_lock_destroy(&wlan_wake_lock);
8731#endif
Madan Mohan Koyyalamudicae253a2012-11-06 19:10:35 -08008732 return -EIO;
Jeff Johnson295189b2012-06-20 16:38:30 -07008733 }
8734
Jeff Johnson295189b2012-06-20 16:38:30 -07008735#ifdef ANI_BUS_TYPE_PCI
8736
8737 dev = wcnss_wlan_get_device();
8738
8739#endif // ANI_BUS_TYPE_PCI
8740
8741#ifdef ANI_BUS_TYPE_PLATFORM
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008742
8743#ifdef HAVE_WCNSS_CAL_DOWNLOAD
8744 /* wait until WCNSS driver downloads NV */
8745 while (!wcnss_device_ready() && 5 >= ++max_retries) {
8746 msleep(1000);
8747 }
8748 if (max_retries >= 5) {
8749 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__);
madan mohan koyyalamudi8c96ce12013-07-10 19:14:39 +05308750#ifdef WLAN_OPEN_SOURCE
8751 wake_lock_destroy(&wlan_wake_lock);
8752#endif
Sameer Thalappilf58d7ec2013-04-25 20:17:12 -07008753 return -ENODEV;
8754 }
8755#endif
8756
Jeff Johnson295189b2012-06-20 16:38:30 -07008757 dev = wcnss_wlan_get_device();
8758#endif // ANI_BUS_TYPE_PLATFORM
8759
8760
8761 do {
8762 if (NULL == dev) {
8763 hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN device not found!!",__func__);
8764 ret_status = -1;
8765 break;
8766 }
8767
Jeff Johnson295189b2012-06-20 16:38:30 -07008768#ifdef TIMER_MANAGER
8769 vos_timer_manager_init();
8770#endif
8771
8772 /* Preopen VOSS so that it is ready to start at least SAL */
8773 status = vos_preOpen(&pVosContext);
8774
8775 if (!VOS_IS_STATUS_SUCCESS(status))
8776 {
8777 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Failed to preOpen VOSS", __func__);
8778 ret_status = -1;
8779 break;
8780 }
8781
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008782#ifndef MODULE
8783 /* For statically linked driver, call hdd_set_conparam to update curr_con_mode
8784 */
8785 hdd_set_conparam((v_UINT_t)con_mode);
8786#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008787
8788 // Call our main init function
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008789 if (hdd_wlan_startup(dev))
8790 {
Jeff Johnson295189b2012-06-20 16:38:30 -07008791 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WLAN Driver Initialization failed",
Jeff Johnsonbc676b42013-02-14 16:04:08 -08008792 __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07008793 vos_preClose( &pVosContext );
8794 ret_status = -1;
8795 break;
8796 }
8797
8798 /* Cancel the vote for XO Core ON
8799 * This is done here for safety purposes in case we re-initialize without turning
8800 * it OFF in any error scenario.
8801 */
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008802 hddLog(VOS_TRACE_LEVEL_INFO, "In module init: Ensure Force XO Core is OFF"
Jeff Johnson295189b2012-06-20 16:38:30 -07008803 " when WLAN is turned ON so Core toggles"
Madan Mohan Koyyalamudi8b7f1e62012-10-05 14:56:51 -07008804 " unless we enter PSD");
Jeff Johnson295189b2012-06-20 16:38:30 -07008805 if (vos_chipVoteXOCore(NULL, NULL, NULL, VOS_FALSE) != VOS_STATUS_SUCCESS)
8806 {
8807 hddLog(VOS_TRACE_LEVEL_ERROR, "Could not cancel XO Core ON vote. Not returning failure."
Arif Hussain6d2a3322013-11-17 19:50:10 -08008808 " Power consumed will be high");
Jeff Johnson295189b2012-06-20 16:38:30 -07008809 }
8810 } while (0);
8811
8812 if (0 != ret_status)
8813 {
8814 //Assert Deep sleep signal now to put Libra HW in lowest power state
8815 status = vos_chipAssertDeepSleep( NULL, NULL, NULL );
8816 VOS_ASSERT( VOS_IS_STATUS_SUCCESS( status) );
8817
8818 //Vote off any PMIC voltage supplies
8819 vos_chipPowerDown(NULL, NULL, NULL);
8820#ifdef TIMER_MANAGER
8821 vos_timer_exit();
8822#endif
8823#ifdef MEMORY_DEBUG
8824 vos_mem_exit();
8825#endif
8826
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008827#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008828 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008829#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008830 pr_err("%s: driver load failure\n", WLAN_MODULE_NAME);
8831 }
8832 else
8833 {
8834 //Send WLAN UP indication to Nlink Service
8835 send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0);
8836
8837 pr_info("%s: driver loaded\n", WLAN_MODULE_NAME);
Jeff Johnson295189b2012-06-20 16:38:30 -07008838 }
8839
8840 EXIT();
8841
8842 return ret_status;
8843}
8844
Jeff Johnson32d95a32012-09-10 13:15:23 -07008845/**---------------------------------------------------------------------------
8846
8847 \brief hdd_module_init() - Init Function
8848
8849 This is the driver entry point (invoked when module is loaded using insmod)
8850
8851 \param - None
8852
8853 \return - 0 for success, non zero for failure
8854
8855 --------------------------------------------------------------------------*/
8856#ifdef MODULE
8857static int __init hdd_module_init ( void)
8858{
8859 return hdd_driver_init();
8860}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008861#else /* #ifdef MODULE */
8862static int __init hdd_module_init ( void)
8863{
8864 /* Driver initialization is delayed to fwpath_changed_handler */
8865 return 0;
8866}
Jeff Johnson32d95a32012-09-10 13:15:23 -07008867#endif /* #ifdef MODULE */
8868
Jeff Johnson295189b2012-06-20 16:38:30 -07008869
8870/**---------------------------------------------------------------------------
8871
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008872 \brief hdd_driver_exit() - Exit function
Jeff Johnson295189b2012-06-20 16:38:30 -07008873
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008874 This is the driver exit point (invoked when module is unloaded using rmmod
8875 or con_mode was changed by userspace)
Jeff Johnson295189b2012-06-20 16:38:30 -07008876
8877 \param - None
8878
8879 \return - None
8880
8881 --------------------------------------------------------------------------*/
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008882static void hdd_driver_exit(void)
Jeff Johnson295189b2012-06-20 16:38:30 -07008883{
8884 hdd_context_t *pHddCtx = NULL;
8885 v_CONTEXT_t pVosContext = NULL;
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008886 int retry = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07008887
8888 pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR);
8889
8890 //Get the global vos context
8891 pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL);
8892
8893 if(!pVosContext)
8894 {
8895 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__);
8896 goto done;
8897 }
8898
8899 //Get the HDD context.
8900 pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext );
8901
8902 if(!pHddCtx)
8903 {
8904 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: module exit called before probe",__func__);
8905 }
8906 else
8907 {
Sameer Thalappil14067972014-01-23 14:54:54 -08008908 while (pHddCtx->isLogpInProgress) {
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008909 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8910 "%s:SSR in Progress; block rmmod for 1 second!!!", __func__);
Jeff Johnsone7245742012-09-05 17:12:55 -07008911 msleep(1000);
Sameer Thalappil451ebb92013-06-28 15:49:58 -07008912
8913 if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) {
8914 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
8915 "%s:SSR never completed, fatal error", __func__);
8916 VOS_BUG(0);
8917 }
8918 }
8919
Jeff Johnson295189b2012-06-20 16:38:30 -07008920
8921 pHddCtx->isLoadUnloadInProgress = TRUE;
8922 vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE);
8923
8924 //Do all the cleanup before deregistering the driver
8925 hdd_wlan_exit(pHddCtx);
8926 }
8927
Jeff Johnson295189b2012-06-20 16:38:30 -07008928 vos_preClose( &pVosContext );
8929
8930#ifdef TIMER_MANAGER
8931 vos_timer_exit();
8932#endif
8933#ifdef MEMORY_DEBUG
8934 vos_mem_exit();
8935#endif
8936
Gopichand Nakkalad0774962013-05-24 11:32:21 +05308937#ifdef WCONN_TRACE_KMSG_LOG_BUFF
8938 vos_wconn_trace_exit();
8939#endif
8940
Jeff Johnson295189b2012-06-20 16:38:30 -07008941done:
Sameer Thalappil50dc0092013-02-19 17:23:33 -08008942#ifdef WLAN_OPEN_SOURCE
Jeff Johnson295189b2012-06-20 16:38:30 -07008943 wake_lock_destroy(&wlan_wake_lock);
Jeff Johnsone7245742012-09-05 17:12:55 -07008944#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07008945 pr_info("%s: driver unloaded\n", WLAN_MODULE_NAME);
8946}
8947
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07008948/**---------------------------------------------------------------------------
8949
8950 \brief hdd_module_exit() - Exit function
8951
8952 This is the driver exit point (invoked when module is unloaded using rmmod)
8953
8954 \param - None
8955
8956 \return - None
8957
8958 --------------------------------------------------------------------------*/
8959static void __exit hdd_module_exit(void)
8960{
8961 hdd_driver_exit();
8962}
8963
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008964#ifdef MODULE
8965static int fwpath_changed_handler(const char *kmessage,
8966 struct kernel_param *kp)
8967{
Jeff Johnson76052702013-04-16 13:55:05 -07008968 return param_set_copystring(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008969}
8970
8971static int con_mode_handler(const char *kmessage,
8972 struct kernel_param *kp)
8973{
Madan Mohan Koyyalamudif2f8d8b2012-10-11 17:06:59 -07008974 return param_set_int(kmessage, kp);
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008975}
8976#else /* #ifdef MODULE */
8977/**---------------------------------------------------------------------------
8978
Jeff Johnson76052702013-04-16 13:55:05 -07008979 \brief kickstart_driver
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008980
Jeff Johnson76052702013-04-16 13:55:05 -07008981 This is the driver entry point
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008982 - delayed driver initialization when driver is statically linked
Jeff Johnson76052702013-04-16 13:55:05 -07008983 - invoked when module parameter fwpath is modified from userspace to signal
8984 initializing the WLAN driver or when con_mode is modified from userspace
8985 to signal a switch in operating mode
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008986
8987 \return - 0 for success, non zero for failure
8988
8989 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07008990static int kickstart_driver(void)
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008991{
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07008992 int ret_status;
8993
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07008994 if (!wlan_hdd_inited) {
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
9000 hdd_driver_exit();
Jeff Johnson76052702013-04-16 13:55:05 -07009001
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009002 msleep(200);
Jeff Johnson76052702013-04-16 13:55:05 -07009003
Madan Mohan Koyyalamudi62e60052012-10-05 14:27:22 -07009004 ret_status = hdd_driver_init();
9005 wlan_hdd_inited = ret_status ? 0 : 1;
9006 return ret_status;
Madan Mohan Koyyalamudic2ec3bd2012-09-18 19:49:40 -07009007}
9008
Jeff Johnson295189b2012-06-20 16:38:30 -07009009/**---------------------------------------------------------------------------
9010
Jeff Johnson76052702013-04-16 13:55:05 -07009011 \brief fwpath_changed_handler() - Handler Function
9012
9013 Handle changes to the fwpath parameter
9014
9015 \return - 0 for success, non zero for failure
9016
9017 --------------------------------------------------------------------------*/
9018static int fwpath_changed_handler(const char *kmessage,
9019 struct kernel_param *kp)
9020{
9021 int ret;
9022
9023 ret = param_set_copystring(kmessage, kp);
9024 if (0 == ret)
9025 ret = kickstart_driver();
9026 return ret;
9027}
9028
9029/**---------------------------------------------------------------------------
9030
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009031 \brief con_mode_handler() -
9032
9033 Handler function for module param con_mode when it is changed by userspace
9034 Dynamically linked - do nothing
9035 Statically linked - exit and init driver, as in rmmod and insmod
9036
Jeff Johnson76052702013-04-16 13:55:05 -07009037 \param -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009038
Jeff Johnson76052702013-04-16 13:55:05 -07009039 \return -
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009040
9041 --------------------------------------------------------------------------*/
Jeff Johnson76052702013-04-16 13:55:05 -07009042static int con_mode_handler(const char *kmessage, struct kernel_param *kp)
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009043{
Jeff Johnson76052702013-04-16 13:55:05 -07009044 int ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009045
Jeff Johnson76052702013-04-16 13:55:05 -07009046 ret = param_set_int(kmessage, kp);
9047 if (0 == ret)
9048 ret = kickstart_driver();
9049 return ret;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009050}
9051#endif /* #ifdef MODULE */
9052
9053/**---------------------------------------------------------------------------
9054
Jeff Johnson295189b2012-06-20 16:38:30 -07009055 \brief hdd_get_conparam() -
9056
9057 This is the driver exit point (invoked when module is unloaded using rmmod)
9058
9059 \param - None
9060
9061 \return - tVOS_CON_MODE
9062
9063 --------------------------------------------------------------------------*/
9064tVOS_CON_MODE hdd_get_conparam ( void )
9065{
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009066#ifdef MODULE
Jeff Johnson295189b2012-06-20 16:38:30 -07009067 return (tVOS_CON_MODE)con_mode;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009068#else
9069 return (tVOS_CON_MODE)curr_con_mode;
9070#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009071}
9072void hdd_set_conparam ( v_UINT_t newParam )
9073{
9074 con_mode = newParam;
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009075#ifndef MODULE
9076 curr_con_mode = con_mode;
9077#endif
Jeff Johnson295189b2012-06-20 16:38:30 -07009078}
9079/**---------------------------------------------------------------------------
9080
9081 \brief hdd_softap_sta_deauth() - function
9082
9083 This to take counter measure to handle deauth req from HDD
9084
9085 \param - pAdapter - Pointer to the HDD
9086
9087 \param - enable - boolean value
9088
9089 \return - None
9090
9091 --------------------------------------------------------------------------*/
9092
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009093VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddress)
Jeff Johnson295189b2012-06-20 16:38:30 -07009094{
Jeff Johnson295189b2012-06-20 16:38:30 -07009095 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009096 VOS_STATUS vosStatus = VOS_STATUS_E_FAULT;
Jeff Johnson295189b2012-06-20 16:38:30 -07009097
9098 ENTER();
9099
Rajesh Chauhan18488fc2013-08-22 10:15:03 -07009100 hddLog(LOG1, "hdd_softap_sta_deauth:(%p, false)",
9101 (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009102
9103 //Ignore request to deauth bcmc station
9104 if( pDestMacAddress[0] & 0x1 )
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009105 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009106
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009107 vosStatus = WLANSAP_DeauthSta(pVosContext,pDestMacAddress);
Jeff Johnson295189b2012-06-20 16:38:30 -07009108
9109 EXIT();
Madan Mohan Koyyalamudicd784992013-01-11 15:30:36 -08009110 return vosStatus;
Jeff Johnson295189b2012-06-20 16:38:30 -07009111}
9112
9113/**---------------------------------------------------------------------------
9114
9115 \brief hdd_softap_sta_disassoc() - function
9116
9117 This to take counter measure to handle deauth req from HDD
9118
9119 \param - pAdapter - Pointer to the HDD
9120
9121 \param - enable - boolean value
9122
9123 \return - None
9124
9125 --------------------------------------------------------------------------*/
9126
9127void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress)
9128{
9129 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9130
9131 ENTER();
9132
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309133 hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009134
9135 //Ignore request to disassoc bcmc station
9136 if( pDestMacAddress[0] & 0x1 )
9137 return;
9138
9139 WLANSAP_DisassocSta(pVosContext,pDestMacAddress);
9140}
9141
9142void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t enable)
9143{
9144 v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext;
9145
9146 ENTER();
9147
Gopichand Nakkala66c0bd02013-04-10 11:36:29 +05309148 hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext);
Jeff Johnson295189b2012-06-20 16:38:30 -07009149
9150 WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable);
9151}
9152
Jeff Johnson295189b2012-06-20 16:38:30 -07009153/**---------------------------------------------------------------------------
9154 *
9155 * \brief hdd_get__concurrency_mode() -
9156 *
9157 *
9158 * \param - None
9159 *
9160 * \return - CONCURRENCY MODE
9161 *
9162 * --------------------------------------------------------------------------*/
9163tVOS_CONCURRENCY_MODE hdd_get_concurrency_mode ( void )
9164{
9165 v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL );
9166 hdd_context_t *pHddCtx;
9167
9168 if (NULL != pVosContext)
9169 {
9170 pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext);
9171 if (NULL != pHddCtx)
9172 {
9173 return (tVOS_CONCURRENCY_MODE)pHddCtx->concurrency_mode;
9174 }
9175 }
9176
9177 /* we are in an invalid state :( */
Madan Mohan Koyyalamudi87054ba2012-11-02 13:24:12 -07009178 hddLog(LOGE, "%s: Invalid context", __func__);
Jeff Johnson295189b2012-06-20 16:38:30 -07009179 return VOS_STA;
9180}
9181
9182/* Decide whether to allow/not the apps power collapse.
9183 * Allow apps power collapse if we are in connected state.
9184 * if not, allow only if we are in IMPS */
9185v_BOOL_t hdd_is_apps_power_collapse_allowed(hdd_context_t* pHddCtx)
9186{
9187 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
Srikant Kuppafef66a72013-01-30 17:32:44 -08009188 tANI_BOOLEAN scanRspPending = csrNeighborRoamScanRspPending(pHddCtx->hHal);
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009189 tANI_BOOLEAN inMiddleOfRoaming = csrNeighborMiddleOfRoaming(pHddCtx->hHal);
Jeff Johnson295189b2012-06-20 16:38:30 -07009190 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9191 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
9192 hdd_adapter_t *pAdapter = NULL;
9193 VOS_STATUS status;
Yathish9f22e662012-12-10 14:21:35 -08009194 tVOS_CONCURRENCY_MODE concurrent_state = 0;
Jeff Johnson295189b2012-06-20 16:38:30 -07009195
Jeff Johnson295189b2012-06-20 16:38:30 -07009196 if (VOS_STA_SAP_MODE == hdd_get_conparam())
9197 return TRUE;
Jeff Johnson295189b2012-06-20 16:38:30 -07009198
Yathish9f22e662012-12-10 14:21:35 -08009199 concurrent_state = hdd_get_concurrency_mode();
9200
9201#ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE
9202 if(((concurrent_state == (VOS_STA | VOS_P2P_CLIENT)) ||
9203 (concurrent_state == (VOS_STA | VOS_P2P_GO))) &&
9204 (IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE))
9205 return TRUE;
9206#endif
9207
Jeff Johnson295189b2012-06-20 16:38:30 -07009208 /*loop through all adapters. TBD fix for Concurrency */
9209 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9210 while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status )
9211 {
9212 pAdapter = pAdapterNode->pAdapter;
9213 if ( (WLAN_HDD_INFRA_STATION == pAdapter->device_mode)
9214 || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) )
9215 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009216 if (((pConfig->fIsImpsEnabled || pConfig->fIsBmpsEnabled)
Jeff Johnson295189b2012-06-20 16:38:30 -07009217 && (pmcState != IMPS && pmcState != BMPS
Srikant Kuppafef66a72013-01-30 17:32:44 -08009218 && pmcState != STOPPED && pmcState != STANDBY)) ||
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009219 (eANI_BOOLEAN_TRUE == scanRspPending) ||
9220 (eANI_BOOLEAN_TRUE == inMiddleOfRoaming))
Jeff Johnson295189b2012-06-20 16:38:30 -07009221 {
Srikant Kuppafef66a72013-01-30 17:32:44 -08009222 hddLog( LOGE, "%s: do not allow APPS power collapse-"
Srinivas Girigowdaa553c462013-03-07 19:42:52 -08009223 "pmcState = %d scanRspPending = %d inMiddleOfRoaming = %d",
9224 __func__, pmcState, scanRspPending, inMiddleOfRoaming );
Jeff Johnson295189b2012-06-20 16:38:30 -07009225 return FALSE;
9226 }
9227 }
9228 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9229 pAdapterNode = pNext;
9230 }
9231 return TRUE;
9232}
9233
Madan Mohan Koyyalamudic72a4d62012-11-08 14:59:34 -08009234/* Decides whether to send suspend notification to Riva
9235 * if any adapter is in BMPS; then it is required */
9236v_BOOL_t hdd_is_suspend_notify_allowed(hdd_context_t* pHddCtx)
9237{
9238 tPmcState pmcState = pmcGetPmcState(pHddCtx->hHal);
9239 hdd_config_t *pConfig = pHddCtx->cfg_ini;
9240
9241 if (pConfig->fIsBmpsEnabled && (pmcState == BMPS))
9242 {
9243 return TRUE;
9244 }
9245 return FALSE;
9246}
9247
Jeff Johnson295189b2012-06-20 16:38:30 -07009248void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9249{
9250 switch(mode)
9251 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009252 case VOS_STA_MODE:
9253 case VOS_P2P_CLIENT_MODE:
9254 case VOS_P2P_GO_MODE:
9255 case VOS_STA_SAP_MODE:
Jeff Johnsone7245742012-09-05 17:12:55 -07009256 pHddCtx->concurrency_mode |= (1 << mode);
9257 pHddCtx->no_of_sessions[mode]++;
Jeff Johnson295189b2012-06-20 16:38:30 -07009258 break;
9259 default:
9260 break;
9261
9262 }
9263 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9264 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9265}
9266
9267
9268void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode)
9269{
9270 switch(mode)
9271 {
Chilam Ngc4244af2013-04-01 15:37:32 -07009272 case VOS_STA_MODE:
9273 case VOS_P2P_CLIENT_MODE:
9274 case VOS_P2P_GO_MODE:
9275 case VOS_STA_SAP_MODE:
Jeff Johnson295189b2012-06-20 16:38:30 -07009276 pHddCtx->no_of_sessions[mode]--;
9277 if (!(pHddCtx->no_of_sessions[mode]))
9278 pHddCtx->concurrency_mode &= (~(1 << mode));
9279 break;
9280 default:
9281 break;
9282 }
9283 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: concurrency_mode = 0x%x NumberofSessions for mode %d = %d",
9284 __func__,pHddCtx->concurrency_mode,mode,pHddCtx->no_of_sessions[mode]);
9285}
9286
Jeff Johnsone7245742012-09-05 17:12:55 -07009287/**---------------------------------------------------------------------------
9288 *
9289 * \brief wlan_hdd_restart_init
9290 *
9291 * This function initalizes restart timer/flag. An internal function.
9292 *
9293 * \param - pHddCtx
9294 *
9295 * \return - None
9296 *
9297 * --------------------------------------------------------------------------*/
9298
9299static void wlan_hdd_restart_init(hdd_context_t *pHddCtx)
9300{
9301 /* Initialize */
9302 pHddCtx->hdd_restart_retries = 0;
9303 atomic_set(&pHddCtx->isRestartInProgress, 0);
9304 vos_timer_init(&pHddCtx->hdd_restart_timer,
9305 VOS_TIMER_TYPE_SW,
9306 wlan_hdd_restart_timer_cb,
9307 pHddCtx);
9308}
9309/**---------------------------------------------------------------------------
9310 *
9311 * \brief wlan_hdd_restart_deinit
9312 *
9313 * This function cleans up the resources used. An internal function.
9314 *
9315 * \param - pHddCtx
9316 *
9317 * \return - None
9318 *
9319 * --------------------------------------------------------------------------*/
9320
9321static void wlan_hdd_restart_deinit(hdd_context_t* pHddCtx)
9322{
9323
9324 VOS_STATUS vos_status;
9325 /* Block any further calls */
9326 atomic_set(&pHddCtx->isRestartInProgress, 1);
9327 /* Cleanup */
9328 vos_status = vos_timer_stop( &pHddCtx->hdd_restart_timer );
9329 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309330 hddLog(LOGE, FL("Failed to stop HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009331 vos_status = vos_timer_destroy(&pHddCtx->hdd_restart_timer);
9332 if (!VOS_IS_STATUS_SUCCESS(vos_status))
c_hpothu6ff1c3c2013-10-01 19:01:57 +05309333 hddLog(LOGE, FL("Failed to destroy HDD restart timer"));
Jeff Johnsone7245742012-09-05 17:12:55 -07009334
9335}
9336
9337/**---------------------------------------------------------------------------
9338 *
9339 * \brief wlan_hdd_framework_restart
9340 *
9341 * This function uses a cfg80211 API to start a framework initiated WLAN
9342 * driver module unload/load.
9343 *
9344 * Also this API keep retrying (WLAN_HDD_RESTART_RETRY_MAX_CNT).
9345 *
9346 *
9347 * \param - pHddCtx
9348 *
9349 * \return - VOS_STATUS_SUCCESS: Success
9350 * VOS_STATUS_E_EMPTY: Adapter is Empty
9351 * VOS_STATUS_E_NOMEM: No memory
9352
9353 * --------------------------------------------------------------------------*/
9354
9355static VOS_STATUS wlan_hdd_framework_restart(hdd_context_t *pHddCtx)
9356{
9357 VOS_STATUS status = VOS_STATUS_SUCCESS;
9358 hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL;
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009359 int len = (sizeof (struct ieee80211_mgmt));
9360 struct ieee80211_mgmt *mgmt = NULL;
9361
9362 /* Prepare the DEAUTH managment frame with reason code */
9363 mgmt = kzalloc(len, GFP_KERNEL);
9364 if(mgmt == NULL)
9365 {
9366 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9367 "%s: memory allocation failed (%d bytes)", __func__, len);
9368 return VOS_STATUS_E_NOMEM;
9369 }
9370 mgmt->u.deauth.reason_code = WLAN_REASON_DISASSOC_LOW_ACK;
Jeff Johnsone7245742012-09-05 17:12:55 -07009371
9372 /* Iterate over all adapters/devices */
9373 status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode );
9374 do
9375 {
9376 if( (status == VOS_STATUS_SUCCESS) &&
9377 pAdapterNode &&
9378 pAdapterNode->pAdapter)
9379 {
9380 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
9381 "restarting the driver(intf:\'%s\' mode:%d :try %d)",
9382 pAdapterNode->pAdapter->dev->name,
9383 pAdapterNode->pAdapter->device_mode,
9384 pHddCtx->hdd_restart_retries + 1);
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009385 /*
9386 * CFG80211 event to restart the driver
9387 *
9388 * 'cfg80211_send_unprot_deauth' sends a
9389 * NL80211_CMD_UNPROT_DEAUTHENTICATE event to supplicant at any state
9390 * of SME(Linux Kernel) state machine.
9391 *
9392 * Reason code WLAN_REASON_DISASSOC_LOW_ACK is currently used to restart
9393 * the driver.
9394 *
9395 */
9396
9397 cfg80211_send_unprot_deauth(pAdapterNode->pAdapter->dev, (u_int8_t*)mgmt, len );
Jeff Johnsone7245742012-09-05 17:12:55 -07009398 }
9399 status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext );
9400 pAdapterNode = pNext;
9401 } while((NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status));
9402
Madan Mohan Koyyalamudifc19e442013-05-09 18:24:08 -07009403
9404 /* Free the allocated management frame */
9405 kfree(mgmt);
9406
Jeff Johnsone7245742012-09-05 17:12:55 -07009407 /* Retry until we unload or reach max count */
9408 if(++pHddCtx->hdd_restart_retries < WLAN_HDD_RESTART_RETRY_MAX_CNT)
9409 vos_timer_start(&pHddCtx->hdd_restart_timer, WLAN_HDD_RESTART_RETRY_DELAY_MS);
9410
9411 return status;
9412
9413}
9414/**---------------------------------------------------------------------------
9415 *
9416 * \brief wlan_hdd_restart_timer_cb
9417 *
9418 * Restart timer callback. An internal function.
9419 *
9420 * \param - User data:
9421 *
9422 * \return - None
9423 *
9424 * --------------------------------------------------------------------------*/
9425
9426void wlan_hdd_restart_timer_cb(v_PVOID_t usrDataForCallback)
9427{
9428 hdd_context_t *pHddCtx = usrDataForCallback;
9429 wlan_hdd_framework_restart(pHddCtx);
9430 return;
9431
9432}
9433
9434
9435/**---------------------------------------------------------------------------
9436 *
9437 * \brief wlan_hdd_restart_driver
9438 *
9439 * This function sends an event to supplicant to restart the WLAN driver.
9440 *
9441 * This function is called from vos_wlanRestart.
9442 *
9443 * \param - pHddCtx
9444 *
9445 * \return - VOS_STATUS_SUCCESS: Success
9446 * VOS_STATUS_E_EMPTY: Adapter is Empty
9447 * VOS_STATUS_E_ALREADY: Request already in progress
9448
9449 * --------------------------------------------------------------------------*/
9450VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx)
9451{
9452 VOS_STATUS status = VOS_STATUS_SUCCESS;
9453
9454 /* A tight check to make sure reentrancy */
9455 if(atomic_xchg(&pHddCtx->isRestartInProgress, 1))
9456 {
9457 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN,
9458 "%s: WLAN restart is already in progress", __func__);
9459
9460 return VOS_STATUS_E_ALREADY;
9461 }
Sameer Thalappil0c164f52013-03-28 15:27:56 -07009462 /* Send reset FIQ to WCNSS to invoke SSR. */
Madan Mohan Koyyalamudie388b342012-11-08 15:03:16 -08009463#ifdef HAVE_WCNSS_RESET_INTR
Madan Mohan Koyyalamudibb8f0172012-09-28 15:36:06 -07009464 wcnss_reset_intr();
9465#endif
Madan Mohan Koyyalamudi5aef2af2012-10-05 11:56:27 -07009466
Jeff Johnsone7245742012-09-05 17:12:55 -07009467 return status;
9468}
9469
Mihir Shetee1093ba2014-01-21 20:13:32 +05309470/**---------------------------------------------------------------------------
9471 *
9472 * \brief wlan_hdd_init_channels
9473 *
9474 * This function is used to initialize the channel list in CSR
9475 *
9476 * This function is called from hdd_wlan_startup
9477 *
9478 * \param - pHddCtx: HDD context
9479 *
9480 * \return - VOS_STATUS_SUCCESS: Success
9481 * VOS_STATUS_E_FAULT: Failure reported by SME
9482
9483 * --------------------------------------------------------------------------*/
9484static VOS_STATUS wlan_hdd_init_channels(hdd_context_t *pHddCtx)
9485{
9486 eHalStatus status;
9487
9488 status = sme_InitChannels(pHddCtx->hHal);
9489 if (HAL_STATUS_SUCCESS(status))
9490 {
9491 return VOS_STATUS_SUCCESS;
9492 }
9493 else
9494 {
9495 hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Channel initialization failed(%d)",
9496 __func__, status);
9497 return VOS_STATUS_E_FAULT;
9498 }
9499}
9500
Sudhir Sattayappa Kohallib1d8c3a2013-06-18 14:47:20 -07009501/*
9502 * API to find if there is any STA or P2P-Client is connected
9503 */
9504VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx)
9505{
9506 return sme_isSta_p2p_clientConnected(pHddCtx->hHal);
9507}
Jeff Johnsone7245742012-09-05 17:12:55 -07009508
Jeff Johnson295189b2012-06-20 16:38:30 -07009509//Register the module init/exit functions
9510module_init(hdd_module_init);
9511module_exit(hdd_module_exit);
9512
9513MODULE_LICENSE("Dual BSD/GPL");
9514MODULE_AUTHOR("Qualcomm Atheros, Inc.");
9515MODULE_DESCRIPTION("WLAN HOST DEVICE DRIVER");
9516
Madan Mohan Koyyalamudi2331c8a2012-09-18 18:14:48 -07009517module_param_call(con_mode, con_mode_handler, param_get_int, &con_mode,
9518 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Jeff Johnson32d95a32012-09-10 13:15:23 -07009519
Jeff Johnson76052702013-04-16 13:55:05 -07009520module_param_call(fwpath, fwpath_changed_handler, param_get_string, &fwpath,
Jeff Johnson32d95a32012-09-10 13:15:23 -07009521 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
Arif Hussain66559122013-11-21 10:11:40 -08009522
9523module_param(enable_dfs_chan_scan, int,
9524 S_IRUSR | S_IRGRP | S_IROTH);
9525
9526module_param(enable_11d, int,
9527 S_IRUSR | S_IRGRP | S_IROTH);
9528
9529module_param(country_code, charp,
9530 S_IRUSR | S_IRGRP | S_IROTH);